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