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.
5 #include "media/base/channel_layout.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
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 5, // CHANNEL_LAYOUT_4_1_QUAD_SIDE
47 // The channel orderings for each layout as specified by FFmpeg. Each value
48 // represents the index of each channel in each layout. Values of -1 mean the
49 // channel at that index is not used for that layout. For example, the left side
50 // surround sound channel in FFmpeg's 5.1 layout is in the 5th position (because
51 // the order is L, R, C, LFE, LS, RS), so
52 // kChannelOrderings[CHANNEL_LAYOUT_5_1][SIDE_LEFT] = 4;
53 static const int kChannelOrderings[CHANNEL_LAYOUT_MAX + 1][CHANNELS_MAX + 1] = {
54 // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
56 // CHANNEL_LAYOUT_NONE
57 { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
59 // CHANNEL_LAYOUT_UNSUPPORTED
60 { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
62 // CHANNEL_LAYOUT_MONO
63 { -1 , -1 , 0 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
65 // CHANNEL_LAYOUT_STEREO
66 { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
69 { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , 2 , -1 , -1 },
71 // CHANNEL_LAYOUT_SURROUND
72 { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
75 { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , 3 , -1 , -1 },
78 { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , 2 , 3 },
80 // CHANNEL_LAYOUT_QUAD
81 { 0 , 1 , -1 , -1 , 2 , 3 , -1 , -1 , -1 , -1 , -1 },
84 { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , 3 , 4 },
87 { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , -1 , 4 , 5 },
89 // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
91 // CHANNEL_LAYOUT_5_0_BACK
92 { 0 , 1 , 2 , -1 , 3 , 4 , -1 , -1 , -1 , -1 , -1 },
94 // CHANNEL_LAYOUT_5_1_BACK
95 { 0 , 1 , 2 , 3 , 4 , 5 , -1 , -1 , -1 , -1 , -1 },
98 { 0 , 1 , 2 , -1 , 5 , 6 , -1 , -1 , -1 , 3 , 4 },
100 // CHANNEL_LAYOUT_7_1
101 { 0 , 1 , 2 , 3 , 6 , 7 , -1 , -1 , -1 , 4 , 5 },
103 // CHANNEL_LAYOUT_7_1_WIDE
104 { 0 , 1 , 2 , 3 , -1 , -1 , 6 , 7 , -1 , 4 , 5 },
106 // CHANNEL_LAYOUT_STEREO_DOWNMIX
107 { 0 , 1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
109 // CHANNEL_LAYOUT_2POINT1
110 { 0 , 1 , -1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
112 // CHANNEL_LAYOUT_3_1
113 { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
115 // CHANNEL_LAYOUT_4_1
116 { 0 , 1 , 2 , 4 , -1 , -1 , -1 , -1 , 3 , -1 , -1 },
118 // CHANNEL_LAYOUT_6_0
119 { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , 5 , 3 , 4 },
121 // CHANNEL_LAYOUT_6_0_FRONT
122 { 0 , 1 , -1 , -1 , -1 , -1 , 4 , 5 , -1 , 2 , 3 },
124 // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
126 // CHANNEL_LAYOUT_HEXAGONAL
127 { 0 , 1 , 2 , -1 , 3 , 4 , -1 , -1 , 5 , -1 , -1 },
129 // CHANNEL_LAYOUT_6_1
130 { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , 6 , 4 , 5 },
132 // CHANNEL_LAYOUT_6_1_BACK
133 { 0 , 1 , 2 , 3 , 4 , 5 , -1 , -1 , 6 , -1 , -1 },
135 // CHANNEL_LAYOUT_6_1_FRONT
136 { 0 , 1 , -1 , 6 , -1 , -1 , 4 , 5 , -1 , 2 , 3 },
138 // CHANNEL_LAYOUT_7_0_FRONT
139 { 0 , 1 , 2 , -1 , -1 , -1 , 5 , 6 , -1 , 3 , 4 },
141 // CHANNEL_LAYOUT_7_1_WIDE_BACK
142 { 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , -1 , -1 , -1 },
144 // CHANNEL_LAYOUT_OCTAGONAL
145 { 0 , 1 , 2 , -1 , 5 , 6 , -1 , -1 , 7 , 3 , 4 },
147 // CHANNEL_LAYOUT_DISCRETE
148 { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
150 // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC
151 { 0 , 1 , 2 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 },
153 // CHANNEL_LAYOUT_4_1_QUAD_SIDE
154 { 0 , 1 , -1 , 4 , -1 , -1 , -1 , -1 , -1 , 2 , 3 },
156 // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR
159 int ChannelLayoutToChannelCount(ChannelLayout layout) {
160 DCHECK_LT(static_cast<size_t>(layout), arraysize(kLayoutToChannels));
161 return kLayoutToChannels[layout];
164 // Converts a channel count into a channel layout.
165 ChannelLayout GuessChannelLayout(int channels) {
168 return CHANNEL_LAYOUT_MONO;
170 return CHANNEL_LAYOUT_STEREO;
172 return CHANNEL_LAYOUT_SURROUND;
174 return CHANNEL_LAYOUT_QUAD;
176 return CHANNEL_LAYOUT_5_0;
178 return CHANNEL_LAYOUT_5_1;
180 return CHANNEL_LAYOUT_6_1;
182 return CHANNEL_LAYOUT_7_1;
184 DVLOG(1) << "Unsupported channel count: " << channels;
186 return CHANNEL_LAYOUT_UNSUPPORTED;
189 int ChannelOrder(ChannelLayout layout, Channels channel) {
190 DCHECK_LT(static_cast<size_t>(layout), arraysize(kChannelOrderings));
191 DCHECK_LT(static_cast<size_t>(channel), arraysize(kChannelOrderings[0]));
192 return kChannelOrderings[layout][channel];
195 const char* ChannelLayoutToString(ChannelLayout layout) {
197 case CHANNEL_LAYOUT_NONE:
199 case CHANNEL_LAYOUT_UNSUPPORTED:
200 return "UNSUPPORTED";
201 case CHANNEL_LAYOUT_MONO:
203 case CHANNEL_LAYOUT_STEREO:
205 case CHANNEL_LAYOUT_2_1:
207 case CHANNEL_LAYOUT_SURROUND:
209 case CHANNEL_LAYOUT_4_0:
211 case CHANNEL_LAYOUT_2_2:
213 case CHANNEL_LAYOUT_QUAD:
215 case CHANNEL_LAYOUT_5_0:
217 case CHANNEL_LAYOUT_5_1:
219 case CHANNEL_LAYOUT_5_0_BACK:
221 case CHANNEL_LAYOUT_5_1_BACK:
223 case CHANNEL_LAYOUT_7_0:
225 case CHANNEL_LAYOUT_7_1:
227 case CHANNEL_LAYOUT_7_1_WIDE:
229 case CHANNEL_LAYOUT_STEREO_DOWNMIX:
230 return "STEREO_DOWNMIX";
231 case CHANNEL_LAYOUT_2POINT1:
233 case CHANNEL_LAYOUT_3_1:
235 case CHANNEL_LAYOUT_4_1:
237 case CHANNEL_LAYOUT_6_0:
239 case CHANNEL_LAYOUT_6_0_FRONT:
241 case CHANNEL_LAYOUT_HEXAGONAL:
243 case CHANNEL_LAYOUT_6_1:
245 case CHANNEL_LAYOUT_6_1_BACK:
247 case CHANNEL_LAYOUT_6_1_FRONT:
249 case CHANNEL_LAYOUT_7_0_FRONT:
251 case CHANNEL_LAYOUT_7_1_WIDE_BACK:
252 return "7.1_WIDE_BACK";
253 case CHANNEL_LAYOUT_OCTAGONAL:
255 case CHANNEL_LAYOUT_DISCRETE:
257 case CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC:
258 return "STEREO_AND_KEYBOARD_MIC";
259 case CHANNEL_LAYOUT_4_1_QUAD_SIDE:
260 return "4.1_QUAD_SIDE";
262 NOTREACHED() << "Invalid channel layout provided: " << layout;