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