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