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
ChannelLayoutToChannelCount(ChannelLayout layout)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.
GuessChannelLayout(int channels)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
ChannelOrder(ChannelLayout layout,Channels channel)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
ChannelLayoutToString(ChannelLayout layout)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