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 28#include "avstring.h" 29#include "avutil.h" 30#include "channel_layout.h" 31#include "bprint.h" 32#include "common.h" 33 34struct channel_name { 35 const char *name; 36 const char *description; 37}; 38 39static const struct channel_name channel_names[] = { 40 [0] = { "FL", "front left" }, 41 [1] = { "FR", "front right" }, 42 [2] = { "FC", "front center" }, 43 [3] = { "LFE", "low frequency" }, 44 [4] = { "BL", "back left" }, 45 [5] = { "BR", "back right" }, 46 [6] = { "FLC", "front left-of-center" }, 47 [7] = { "FRC", "front right-of-center" }, 48 [8] = { "BC", "back center" }, 49 [9] = { "SL", "side left" }, 50 [10] = { "SR", "side right" }, 51 [11] = { "TC", "top center" }, 52 [12] = { "TFL", "top front left" }, 53 [13] = { "TFC", "top front center" }, 54 [14] = { "TFR", "top front right" }, 55 [15] = { "TBL", "top back left" }, 56 [16] = { "TBC", "top back center" }, 57 [17] = { "TBR", "top back right" }, 58 [29] = { "DL", "downmix left" }, 59 [30] = { "DR", "downmix right" }, 60 [31] = { "WL", "wide left" }, 61 [32] = { "WR", "wide right" }, 62 [33] = { "SDL", "surround direct left" }, 63 [34] = { "SDR", "surround direct right" }, 64 [35] = { "LFE2", "low frequency 2" }, 65}; 66 67static const char *get_channel_name(int channel_id) 68{ 69 if (channel_id < 0 || channel_id >= FF_ARRAY_ELEMS(channel_names)) 70 return NULL; 71 return channel_names[channel_id].name; 72} 73 74static const struct { 75 const char *name; 76 int nb_channels; 77 uint64_t layout; 78} channel_layout_map[] = { 79 { "mono", 1, AV_CH_LAYOUT_MONO }, 80 { "stereo", 2, AV_CH_LAYOUT_STEREO }, 81 { "2.1", 3, AV_CH_LAYOUT_2POINT1 }, 82 { "3.0", 3, AV_CH_LAYOUT_SURROUND }, 83 { "3.0(back)", 3, AV_CH_LAYOUT_2_1 }, 84 { "4.0", 4, AV_CH_LAYOUT_4POINT0 }, 85 { "quad", 4, AV_CH_LAYOUT_QUAD }, 86 { "quad(side)", 4, AV_CH_LAYOUT_2_2 }, 87 { "3.1", 4, AV_CH_LAYOUT_3POINT1 }, 88 { "5.0", 5, AV_CH_LAYOUT_5POINT0_BACK }, 89 { "5.0(side)", 5, AV_CH_LAYOUT_5POINT0 }, 90 { "4.1", 5, AV_CH_LAYOUT_4POINT1 }, 91 { "5.1", 6, AV_CH_LAYOUT_5POINT1_BACK }, 92 { "5.1(side)", 6, AV_CH_LAYOUT_5POINT1 }, 93 { "6.0", 6, AV_CH_LAYOUT_6POINT0 }, 94 { "6.0(front)", 6, AV_CH_LAYOUT_6POINT0_FRONT }, 95 { "hexagonal", 6, AV_CH_LAYOUT_HEXAGONAL }, 96 { "6.1", 7, AV_CH_LAYOUT_6POINT1 }, 97 { "6.1", 7, AV_CH_LAYOUT_6POINT1_BACK }, 98 { "6.1(front)", 7, AV_CH_LAYOUT_6POINT1_FRONT }, 99 { "7.0", 7, AV_CH_LAYOUT_7POINT0 }, 100 { "7.0(front)", 7, AV_CH_LAYOUT_7POINT0_FRONT }, 101 { "7.1", 8, AV_CH_LAYOUT_7POINT1 }, 102 { "7.1(wide)", 8, AV_CH_LAYOUT_7POINT1_WIDE_BACK }, 103 { "7.1(wide-side)", 8, AV_CH_LAYOUT_7POINT1_WIDE }, 104 { "octagonal", 8, AV_CH_LAYOUT_OCTAGONAL }, 105 { "downmix", 2, AV_CH_LAYOUT_STEREO_DOWNMIX, }, 106}; 107 108#if FF_API_GET_CHANNEL_LAYOUT_COMPAT 109static uint64_t get_channel_layout_single(const char *name, int name_len, int compat) 110#else 111static uint64_t get_channel_layout_single(const char *name, int name_len) 112#endif 113{ 114 int i; 115 char *end; 116 int64_t layout; 117 118 for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) { 119 if (strlen(channel_layout_map[i].name) == name_len && 120 !memcmp(channel_layout_map[i].name, name, name_len)) 121 return channel_layout_map[i].layout; 122 } 123 for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) 124 if (channel_names[i].name && 125 strlen(channel_names[i].name) == name_len && 126 !memcmp(channel_names[i].name, name, name_len)) 127 return (int64_t)1 << i; 128 i = strtol(name, &end, 10); 129 130#if FF_API_GET_CHANNEL_LAYOUT_COMPAT 131 if (compat) { 132 if (end - name == name_len || 133 (end + 1 - name == name_len && *end == 'c')) { 134 layout = av_get_default_channel_layout(i); 135 if (end - name == name_len) { 136 av_log(NULL, AV_LOG_WARNING, 137 "Single channel layout '%.*s' is interpreted as a number of channels, " 138 "switch to the syntax '%.*sc' otherwise it will be interpreted as a " 139 "channel layout number in a later version\n", 140 name_len, name, name_len, name); 141 return layout; 142 } 143 } 144 } else { 145#endif 146 if ((end + 1 - name == name_len && *end == 'c')) 147 return av_get_default_channel_layout(i); 148#if FF_API_GET_CHANNEL_LAYOUT_COMPAT 149 } 150#endif 151 152 layout = strtoll(name, &end, 0); 153 if (end - name == name_len) 154 return FFMAX(layout, 0); 155 return 0; 156} 157 158#if FF_API_GET_CHANNEL_LAYOUT_COMPAT 159uint64_t ff_get_channel_layout(const char *name, int compat) 160#else 161uint64_t av_get_channel_layout(const char *name) 162#endif 163{ 164 const char *n, *e; 165 const char *name_end = name + strlen(name); 166 int64_t layout = 0, layout_single; 167 168 for (n = name; n < name_end; n = e + 1) { 169 for (e = n; e < name_end && *e != '+' && *e != '|'; e++); 170#if FF_API_GET_CHANNEL_LAYOUT_COMPAT 171 layout_single = get_channel_layout_single(n, e - n, compat); 172#else 173 layout_single = get_channel_layout_single(n, e - n); 174#endif 175 if (!layout_single) 176 return 0; 177 layout |= layout_single; 178 } 179 return layout; 180} 181 182#if FF_API_GET_CHANNEL_LAYOUT_COMPAT 183uint64_t av_get_channel_layout(const char *name) 184{ 185 return ff_get_channel_layout(name, 1); 186} 187#endif 188 189void av_bprint_channel_layout(struct AVBPrint *bp, 190 int nb_channels, uint64_t channel_layout) 191{ 192 int i; 193 194 if (nb_channels <= 0) 195 nb_channels = av_get_channel_layout_nb_channels(channel_layout); 196 197 for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) 198 if (nb_channels == channel_layout_map[i].nb_channels && 199 channel_layout == channel_layout_map[i].layout) { 200 av_bprintf(bp, "%s", channel_layout_map[i].name); 201 return; 202 } 203 204 av_bprintf(bp, "%d channels", nb_channels); 205 if (channel_layout) { 206 int i, ch; 207 av_bprintf(bp, " ("); 208 for (i = 0, ch = 0; i < 64; i++) { 209 if ((channel_layout & (UINT64_C(1) << i))) { 210 const char *name = get_channel_name(i); 211 if (name) { 212 if (ch > 0) 213 av_bprintf(bp, "+"); 214 av_bprintf(bp, "%s", name); 215 } 216 ch++; 217 } 218 } 219 av_bprintf(bp, ")"); 220 } 221} 222 223void av_get_channel_layout_string(char *buf, int buf_size, 224 int nb_channels, uint64_t channel_layout) 225{ 226 AVBPrint bp; 227 228 av_bprint_init_for_buffer(&bp, buf, buf_size); 229 av_bprint_channel_layout(&bp, nb_channels, channel_layout); 230} 231 232int av_get_channel_layout_nb_channels(uint64_t channel_layout) 233{ 234 return av_popcount64(channel_layout); 235} 236 237int64_t av_get_default_channel_layout(int nb_channels) { 238 int i; 239 for (i = 0; i < FF_ARRAY_ELEMS(channel_layout_map); i++) 240 if (nb_channels == channel_layout_map[i].nb_channels) 241 return channel_layout_map[i].layout; 242 return 0; 243} 244 245int av_get_channel_layout_channel_index(uint64_t channel_layout, 246 uint64_t channel) 247{ 248 if (!(channel_layout & channel) || 249 av_get_channel_layout_nb_channels(channel) != 1) 250 return AVERROR(EINVAL); 251 channel_layout &= channel - 1; 252 return av_get_channel_layout_nb_channels(channel_layout); 253} 254 255const char *av_get_channel_name(uint64_t channel) 256{ 257 int i; 258 if (av_get_channel_layout_nb_channels(channel) != 1) 259 return NULL; 260 for (i = 0; i < 64; i++) 261 if ((1ULL<<i) & channel) 262 return get_channel_name(i); 263 return NULL; 264} 265 266const char *av_get_channel_description(uint64_t channel) 267{ 268 int i; 269 if (av_get_channel_layout_nb_channels(channel) != 1) 270 return NULL; 271 for (i = 0; i < FF_ARRAY_ELEMS(channel_names); i++) 272 if ((1ULL<<i) & channel) 273 return channel_names[i].description; 274 return NULL; 275} 276 277uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index) 278{ 279 int i; 280 281 if (av_get_channel_layout_nb_channels(channel_layout) <= index) 282 return 0; 283 284 for (i = 0; i < 64; i++) { 285 if ((1ULL << i) & channel_layout && !index--) 286 return 1ULL << i; 287 } 288 return 0; 289} 290 291int av_get_standard_channel_layout(unsigned index, uint64_t *layout, 292 const char **name) 293{ 294 if (index >= FF_ARRAY_ELEMS(channel_layout_map)) 295 return AVERROR_EOF; 296 if (layout) *layout = channel_layout_map[index].layout; 297 if (name) *name = channel_layout_map[index].name; 298 return 0; 299} 300