channel_layout.cc (8255B)
1 /* 2 * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "api/audio/channel_layout.h" 12 13 #include <cstddef> 14 #include <iterator> 15 16 #include "rtc_base/checks.h" 17 #include "rtc_base/logging.h" 18 19 namespace webrtc { 20 21 static const int kLayoutToChannels[] = { 22 0, // CHANNEL_LAYOUT_NONE 23 0, // CHANNEL_LAYOUT_UNSUPPORTED 24 1, // CHANNEL_LAYOUT_MONO 25 2, // CHANNEL_LAYOUT_STEREO 26 3, // CHANNEL_LAYOUT_2_1 27 3, // CHANNEL_LAYOUT_SURROUND 28 4, // CHANNEL_LAYOUT_4_0 29 4, // CHANNEL_LAYOUT_2_2 30 4, // CHANNEL_LAYOUT_QUAD 31 5, // CHANNEL_LAYOUT_5_0 32 6, // CHANNEL_LAYOUT_5_1 33 5, // CHANNEL_LAYOUT_5_0_BACK 34 6, // CHANNEL_LAYOUT_5_1_BACK 35 7, // CHANNEL_LAYOUT_7_0 36 8, // CHANNEL_LAYOUT_7_1 37 8, // CHANNEL_LAYOUT_7_1_WIDE 38 2, // CHANNEL_LAYOUT_STEREO_DOWNMIX 39 3, // CHANNEL_LAYOUT_2POINT1 40 4, // CHANNEL_LAYOUT_3_1 41 5, // CHANNEL_LAYOUT_4_1 42 6, // CHANNEL_LAYOUT_6_0 43 6, // CHANNEL_LAYOUT_6_0_FRONT 44 6, // CHANNEL_LAYOUT_HEXAGONAL 45 7, // CHANNEL_LAYOUT_6_1 46 7, // CHANNEL_LAYOUT_6_1_BACK 47 7, // CHANNEL_LAYOUT_6_1_FRONT 48 7, // CHANNEL_LAYOUT_7_0_FRONT 49 8, // CHANNEL_LAYOUT_7_1_WIDE_BACK 50 8, // CHANNEL_LAYOUT_OCTAGONAL 51 0, // CHANNEL_LAYOUT_DISCRETE 52 3, // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC 53 5, // CHANNEL_LAYOUT_4_1_QUAD_SIDE 54 0, // CHANNEL_LAYOUT_BITSTREAM 55 }; 56 57 // The channel orderings for each layout as specified by FFmpeg. Each value 58 // represents the index of each channel in each layout. Values of -1 mean the 59 // channel at that index is not used for that layout. For example, the left side 60 // surround sound channel in FFmpeg's 5.1 layout is in the 5th position (because 61 // the order is L, R, C, LFE, LS, RS), so 62 // kChannelOrderings[CHANNEL_LAYOUT_5_1][SIDE_LEFT] = 4; 63 static const int kChannelOrderings[CHANNEL_LAYOUT_MAX + 1][CHANNELS_MAX + 1] = { 64 // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR 65 66 // CHANNEL_LAYOUT_NONE 67 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 68 69 // CHANNEL_LAYOUT_UNSUPPORTED 70 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 71 72 // CHANNEL_LAYOUT_MONO 73 {-1, -1, 0, -1, -1, -1, -1, -1, -1, -1, -1}, 74 75 // CHANNEL_LAYOUT_STEREO 76 {0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 77 78 // CHANNEL_LAYOUT_2_1 79 {0, 1, -1, -1, -1, -1, -1, -1, 2, -1, -1}, 80 81 // CHANNEL_LAYOUT_SURROUND 82 {0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1}, 83 84 // CHANNEL_LAYOUT_4_0 85 {0, 1, 2, -1, -1, -1, -1, -1, 3, -1, -1}, 86 87 // CHANNEL_LAYOUT_2_2 88 {0, 1, -1, -1, -1, -1, -1, -1, -1, 2, 3}, 89 90 // CHANNEL_LAYOUT_QUAD 91 {0, 1, -1, -1, 2, 3, -1, -1, -1, -1, -1}, 92 93 // CHANNEL_LAYOUT_5_0 94 {0, 1, 2, -1, -1, -1, -1, -1, -1, 3, 4}, 95 96 // CHANNEL_LAYOUT_5_1 97 {0, 1, 2, 3, -1, -1, -1, -1, -1, 4, 5}, 98 99 // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR 100 101 // CHANNEL_LAYOUT_5_0_BACK 102 {0, 1, 2, -1, 3, 4, -1, -1, -1, -1, -1}, 103 104 // CHANNEL_LAYOUT_5_1_BACK 105 {0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1}, 106 107 // CHANNEL_LAYOUT_7_0 108 {0, 1, 2, -1, 5, 6, -1, -1, -1, 3, 4}, 109 110 // CHANNEL_LAYOUT_7_1 111 {0, 1, 2, 3, 6, 7, -1, -1, -1, 4, 5}, 112 113 // CHANNEL_LAYOUT_7_1_WIDE 114 {0, 1, 2, 3, -1, -1, 6, 7, -1, 4, 5}, 115 116 // CHANNEL_LAYOUT_STEREO_DOWNMIX 117 {0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 118 119 // CHANNEL_LAYOUT_2POINT1 120 {0, 1, -1, 2, -1, -1, -1, -1, -1, -1, -1}, 121 122 // CHANNEL_LAYOUT_3_1 123 {0, 1, 2, 3, -1, -1, -1, -1, -1, -1, -1}, 124 125 // CHANNEL_LAYOUT_4_1 126 {0, 1, 2, 4, -1, -1, -1, -1, 3, -1, -1}, 127 128 // CHANNEL_LAYOUT_6_0 129 {0, 1, 2, -1, -1, -1, -1, -1, 5, 3, 4}, 130 131 // CHANNEL_LAYOUT_6_0_FRONT 132 {0, 1, -1, -1, -1, -1, 4, 5, -1, 2, 3}, 133 134 // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR 135 136 // CHANNEL_LAYOUT_HEXAGONAL 137 {0, 1, 2, -1, 3, 4, -1, -1, 5, -1, -1}, 138 139 // CHANNEL_LAYOUT_6_1 140 {0, 1, 2, 3, -1, -1, -1, -1, 6, 4, 5}, 141 142 // CHANNEL_LAYOUT_6_1_BACK 143 {0, 1, 2, 3, 4, 5, -1, -1, 6, -1, -1}, 144 145 // CHANNEL_LAYOUT_6_1_FRONT 146 {0, 1, -1, 6, -1, -1, 4, 5, -1, 2, 3}, 147 148 // CHANNEL_LAYOUT_7_0_FRONT 149 {0, 1, 2, -1, -1, -1, 5, 6, -1, 3, 4}, 150 151 // CHANNEL_LAYOUT_7_1_WIDE_BACK 152 {0, 1, 2, 3, 4, 5, 6, 7, -1, -1, -1}, 153 154 // CHANNEL_LAYOUT_OCTAGONAL 155 {0, 1, 2, -1, 5, 6, -1, -1, 7, 3, 4}, 156 157 // CHANNEL_LAYOUT_DISCRETE 158 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 159 160 // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC 161 {0, 1, 2, -1, -1, -1, -1, -1, -1, -1, -1}, 162 163 // CHANNEL_LAYOUT_4_1_QUAD_SIDE 164 {0, 1, -1, 4, -1, -1, -1, -1, -1, 2, 3}, 165 166 // CHANNEL_LAYOUT_BITSTREAM 167 {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}, 168 169 // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR 170 }; 171 172 int ChannelLayoutToChannelCount(ChannelLayout layout) { 173 RTC_DCHECK_LT(static_cast<size_t>(layout), std::size(kLayoutToChannels)); 174 RTC_DCHECK_LE(kLayoutToChannels[layout], kMaxConcurrentChannels); 175 return kLayoutToChannels[layout]; 176 } 177 178 // Converts a channel count into a channel layout. 179 ChannelLayout GuessChannelLayout(int channels) { 180 switch (channels) { 181 case 1: 182 return CHANNEL_LAYOUT_MONO; 183 case 2: 184 return CHANNEL_LAYOUT_STEREO; 185 case 3: 186 return CHANNEL_LAYOUT_SURROUND; 187 case 4: 188 return CHANNEL_LAYOUT_QUAD; 189 case 5: 190 return CHANNEL_LAYOUT_5_0; 191 case 6: 192 return CHANNEL_LAYOUT_5_1; 193 case 7: 194 return CHANNEL_LAYOUT_6_1; 195 case 8: 196 return CHANNEL_LAYOUT_7_1; 197 default: 198 RTC_DLOG(LS_WARNING) << "Unsupported channel count: " << channels; 199 } 200 return CHANNEL_LAYOUT_UNSUPPORTED; 201 } 202 203 int ChannelOrder(ChannelLayout layout, Channels channel) { 204 RTC_DCHECK_LT(static_cast<size_t>(layout), std::size(kChannelOrderings)); 205 RTC_DCHECK_LT(static_cast<size_t>(channel), std::size(kChannelOrderings[0])); 206 return kChannelOrderings[layout][channel]; 207 } 208 209 const char* ChannelLayoutToString(ChannelLayout layout) { 210 switch (layout) { 211 case CHANNEL_LAYOUT_NONE: 212 return "NONE"; 213 case CHANNEL_LAYOUT_UNSUPPORTED: 214 return "UNSUPPORTED"; 215 case CHANNEL_LAYOUT_MONO: 216 return "MONO"; 217 case CHANNEL_LAYOUT_STEREO: 218 return "STEREO"; 219 case CHANNEL_LAYOUT_2_1: 220 return "2.1"; 221 case CHANNEL_LAYOUT_SURROUND: 222 return "SURROUND"; 223 case CHANNEL_LAYOUT_4_0: 224 return "4.0"; 225 case CHANNEL_LAYOUT_2_2: 226 return "QUAD_SIDE"; 227 case CHANNEL_LAYOUT_QUAD: 228 return "QUAD"; 229 case CHANNEL_LAYOUT_5_0: 230 return "5.0"; 231 case CHANNEL_LAYOUT_5_1: 232 return "5.1"; 233 case CHANNEL_LAYOUT_5_0_BACK: 234 return "5.0_BACK"; 235 case CHANNEL_LAYOUT_5_1_BACK: 236 return "5.1_BACK"; 237 case CHANNEL_LAYOUT_7_0: 238 return "7.0"; 239 case CHANNEL_LAYOUT_7_1: 240 return "7.1"; 241 case CHANNEL_LAYOUT_7_1_WIDE: 242 return "7.1_WIDE"; 243 case CHANNEL_LAYOUT_STEREO_DOWNMIX: 244 return "STEREO_DOWNMIX"; 245 case CHANNEL_LAYOUT_2POINT1: 246 return "2POINT1"; 247 case CHANNEL_LAYOUT_3_1: 248 return "3.1"; 249 case CHANNEL_LAYOUT_4_1: 250 return "4.1"; 251 case CHANNEL_LAYOUT_6_0: 252 return "6.0"; 253 case CHANNEL_LAYOUT_6_0_FRONT: 254 return "6.0_FRONT"; 255 case CHANNEL_LAYOUT_HEXAGONAL: 256 return "HEXAGONAL"; 257 case CHANNEL_LAYOUT_6_1: 258 return "6.1"; 259 case CHANNEL_LAYOUT_6_1_BACK: 260 return "6.1_BACK"; 261 case CHANNEL_LAYOUT_6_1_FRONT: 262 return "6.1_FRONT"; 263 case CHANNEL_LAYOUT_7_0_FRONT: 264 return "7.0_FRONT"; 265 case CHANNEL_LAYOUT_7_1_WIDE_BACK: 266 return "7.1_WIDE_BACK"; 267 case CHANNEL_LAYOUT_OCTAGONAL: 268 return "OCTAGONAL"; 269 case CHANNEL_LAYOUT_DISCRETE: 270 return "DISCRETE"; 271 case CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC: 272 return "STEREO_AND_KEYBOARD_MIC"; 273 case CHANNEL_LAYOUT_4_1_QUAD_SIDE: 274 return "4.1_QUAD_SIDE"; 275 case CHANNEL_LAYOUT_BITSTREAM: 276 return "BITSTREAM"; 277 } 278 RTC_DCHECK_NOTREACHED() << "Invalid channel layout provided: " << layout; 279 return ""; 280 } 281 282 } // namespace webrtc