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