Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/AudioConfig.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "AudioConfig.h"
8
9
namespace mozilla {
10
11
typedef AudioConfig::ChannelLayout ChannelLayout;
12
13
/**
14
 * AudioConfig::ChannelLayout
15
 */
16
17
/*
18
 SMPTE channel layout (also known as wave order)
19
 DUAL-MONO      L   R
20
 DUAL-MONO-LFE  L   R   LFE
21
 MONO           M
22
 MONO-LFE       M   LFE
23
 STEREO         L   R
24
 STEREO-LFE     L   R   LFE
25
 3F             L   R   C
26
 3F-LFE         L   R   C    LFE
27
 2F1            L   R   S
28
 2F1-LFE        L   R   LFE  S
29
 3F1            L   R   C    S
30
 3F1-LFE        L   R   C    LFE S
31
 2F2            L   R   LS   RS
32
 2F2-LFE        L   R   LFE  LS   RS
33
 3F2            L   R   C    LS   RS
34
 3F2-LFE        L   R   C    LFE  LS   RS
35
 3F3R-LFE       L   R   C    LFE  BC   LS   RS
36
 3F4-LFE        L   R   C    LFE  Rls  Rrs  LS   RS
37
*/
38
39
void
40
AudioConfig::ChannelLayout::UpdateChannelMap()
41
0
{
42
0
  mValid = mChannels.Length() <= MAX_CHANNELS;
43
0
  mChannelMap = UNKNOWN_MAP;
44
0
  if (mValid) {
45
0
    mChannelMap = Map();
46
0
    mValid = mChannelMap > 0;
47
0
  }
48
0
}
49
50
auto
51
AudioConfig::ChannelLayout::Map() const -> ChannelMap
52
0
{
53
0
  if (mChannelMap != UNKNOWN_MAP) {
54
0
    return mChannelMap;
55
0
  }
56
0
  if (mChannels.Length() > MAX_CHANNELS) {
57
0
    return UNKNOWN_MAP;
58
0
  }
59
0
  ChannelMap map = UNKNOWN_MAP;
60
0
  for (size_t i = 0; i < mChannels.Length(); i++) {
61
0
    if (uint32_t(mChannels[i]) > sizeof(ChannelMap) * 8) {
62
0
      return UNKNOWN_MAP;
63
0
    }
64
0
    ChannelMap mask = 1 << mChannels[i];
65
0
    if (mChannels[i] == CHANNEL_INVALID || (mChannelMap & mask)) {
66
0
      // Invalid configuration.
67
0
      return UNKNOWN_MAP;
68
0
    }
69
0
    map |= mask;
70
0
  }
71
0
  return map;
72
0
}
73
74
const AudioConfig::Channel*
75
AudioConfig::ChannelLayout::DefaultLayoutForChannels(uint32_t aChannels) const
76
{
77
  switch (aChannels) {
78
    case 1: // MONO
79
    {
80
      static const Channel config[] = { CHANNEL_FRONT_CENTER };
81
      return config;
82
    }
83
    case 2: // STEREO
84
    {
85
      static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT };
86
      return config;
87
    }
88
    case 3: // 3F
89
    {
90
      static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER };
91
      return config;
92
    }
93
    case 4: // QUAD
94
    {
95
      static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT };
96
      return config;
97
    }
98
    case 5: // 3F2
99
    {
100
      static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
101
      return config;
102
    }
103
    case 6: // 3F2-LFE
104
    {
105
      static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
106
      return config;
107
    }
108
    case 7: // 3F3R-LFE
109
    {
110
      static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_BACK_CENTER, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
111
      return config;
112
    }
113
    case 8: // 3F4-LFE
114
    {
115
      static const Channel config[] = { CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT, CHANNEL_FRONT_CENTER, CHANNEL_LFE, CHANNEL_BACK_LEFT, CHANNEL_BACK_RIGHT, CHANNEL_SIDE_LEFT, CHANNEL_SIDE_RIGHT };
116
      return config;
117
    }
118
    default:
119
      return nullptr;
120
  }
121
}
122
123
/* static */ AudioConfig::ChannelLayout
124
AudioConfig::ChannelLayout::SMPTEDefault(
125
  const ChannelLayout& aChannelLayout)
126
0
{
127
0
  if (!aChannelLayout.IsValid()) {
128
0
    return aChannelLayout;
129
0
  }
130
0
  return SMPTEDefault(aChannelLayout.Map());
131
0
}
132
133
/* static */ ChannelLayout
134
AudioConfig::ChannelLayout::SMPTEDefault(ChannelMap aMap)
135
0
{
136
0
  // First handle the most common cases.
137
0
  switch (aMap) {
138
0
    case LMONO_MAP:
139
0
      return ChannelLayout{ CHANNEL_FRONT_CENTER };
140
0
    case LSTEREO_MAP:
141
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT, CHANNEL_FRONT_RIGHT };
142
0
    case L3F_MAP:
143
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
144
0
                            CHANNEL_FRONT_RIGHT,
145
0
                            CHANNEL_FRONT_CENTER };
146
0
    case L3F_LFE_MAP:
147
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
148
0
                            CHANNEL_FRONT_RIGHT,
149
0
                            CHANNEL_FRONT_CENTER,
150
0
                            CHANNEL_LFE };
151
0
    case L2F1_MAP:
152
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
153
0
                            CHANNEL_FRONT_RIGHT,
154
0
                            CHANNEL_BACK_CENTER };
155
0
    case L2F1_LFE_MAP:
156
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
157
0
                            CHANNEL_FRONT_RIGHT,
158
0
                            CHANNEL_LFE,
159
0
                            CHANNEL_BACK_CENTER };
160
0
    case L3F1_MAP:
161
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
162
0
                            CHANNEL_FRONT_RIGHT,
163
0
                            CHANNEL_FRONT_CENTER,
164
0
                            CHANNEL_BACK_CENTER };
165
0
    case L3F1_LFE_MAP:
166
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
167
0
                            CHANNEL_FRONT_RIGHT,
168
0
                            CHANNEL_FRONT_CENTER,
169
0
                            CHANNEL_LFE,
170
0
                            CHANNEL_BACK_CENTER };
171
0
    case L2F2_MAP:
172
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
173
0
                            CHANNEL_FRONT_RIGHT,
174
0
                            CHANNEL_SIDE_LEFT,
175
0
                            CHANNEL_SIDE_RIGHT };
176
0
    case L2F2_LFE_MAP:
177
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
178
0
                            CHANNEL_FRONT_RIGHT,
179
0
                            CHANNEL_LFE,
180
0
                            CHANNEL_SIDE_LEFT,
181
0
                            CHANNEL_SIDE_RIGHT };
182
0
    case LQUAD_MAP:
183
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
184
0
                            CHANNEL_FRONT_RIGHT,
185
0
                            CHANNEL_BACK_LEFT,
186
0
                            CHANNEL_BACK_RIGHT };
187
0
    case LQUAD_LFE_MAP:
188
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
189
0
                            CHANNEL_FRONT_RIGHT,
190
0
                            CHANNEL_LFE,
191
0
                            CHANNEL_BACK_LEFT,
192
0
                            CHANNEL_BACK_RIGHT };
193
0
    case L3F2_MAP:
194
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
195
0
                            CHANNEL_FRONT_RIGHT,
196
0
                            CHANNEL_FRONT_CENTER,
197
0
                            CHANNEL_SIDE_LEFT,
198
0
                            CHANNEL_SIDE_RIGHT };
199
0
    case L3F2_LFE_MAP:
200
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,   CHANNEL_FRONT_RIGHT,
201
0
                            CHANNEL_FRONT_CENTER, CHANNEL_LFE,
202
0
                            CHANNEL_SIDE_LEFT,    CHANNEL_SIDE_RIGHT };
203
0
    case L3F2_BACK_MAP:
204
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,
205
0
                            CHANNEL_FRONT_RIGHT,
206
0
                            CHANNEL_FRONT_CENTER,
207
0
                            CHANNEL_BACK_LEFT,
208
0
                            CHANNEL_BACK_RIGHT };
209
0
    case L3F2_BACK_LFE_MAP:
210
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,   CHANNEL_FRONT_RIGHT,
211
0
                            CHANNEL_FRONT_CENTER, CHANNEL_LFE,
212
0
                            CHANNEL_BACK_LEFT,    CHANNEL_BACK_RIGHT };
213
0
    case L3F3R_LFE_MAP:
214
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,   CHANNEL_FRONT_RIGHT,
215
0
                            CHANNEL_FRONT_CENTER, CHANNEL_LFE,
216
0
                            CHANNEL_BACK_CENTER,  CHANNEL_SIDE_LEFT,
217
0
                            CHANNEL_SIDE_RIGHT };
218
0
    case L3F4_LFE_MAP:
219
0
      return ChannelLayout{ CHANNEL_FRONT_LEFT,   CHANNEL_FRONT_RIGHT,
220
0
                            CHANNEL_FRONT_CENTER, CHANNEL_LFE,
221
0
                            CHANNEL_BACK_LEFT,    CHANNEL_BACK_RIGHT,
222
0
                            CHANNEL_SIDE_LEFT,    CHANNEL_SIDE_RIGHT };
223
0
    default:
224
0
      break;
225
0
  }
226
0
227
0
  static_assert(MAX_CHANNELS <= sizeof(ChannelMap) * 8,
228
0
                "Must be able to fit channels on bit mask");
229
0
  AutoTArray<Channel, MAX_CHANNELS> layout;
230
0
  uint32_t channels = 0;
231
0
232
0
  uint32_t i = 0;
233
0
  while (aMap) {
234
0
    if (aMap & 1) {
235
0
      channels++;
236
0
      if (channels > MAX_CHANNELS) {
237
0
        return ChannelLayout();
238
0
      }
239
0
      layout.AppendElement(static_cast<Channel>(i));
240
0
    }
241
0
    aMap >>= 1;
242
0
    i++;
243
0
  }
244
0
  return ChannelLayout(channels, layout.Elements());
245
0
}
246
247
bool
248
AudioConfig::ChannelLayout::MappingTable(const ChannelLayout& aOther,
249
                                         nsTArray<uint8_t>* aMap) const
250
0
{
251
0
  if (!IsValid() || !aOther.IsValid() || Map() != aOther.Map()) {
252
0
    if (aMap) {
253
0
      aMap->SetLength(0);
254
0
    }
255
0
    return false;
256
0
  }
257
0
  if (!aMap) {
258
0
    return true;
259
0
  }
260
0
  aMap->SetLength(Count());
261
0
  for (uint32_t i = 0; i < Count(); i++) {
262
0
    for (uint32_t j = 0; j < Count(); j++) {
263
0
      if (aOther[j] == mChannels[i]) {
264
0
        (*aMap)[j] = i;
265
0
        break;
266
0
      }
267
0
    }
268
0
  }
269
0
  return true;
270
0
}
271
272
/**
273
 * AudioConfig::ChannelConfig
274
 */
275
276
/* static */ const char*
277
AudioConfig::FormatToString(AudioConfig::SampleFormat aFormat)
278
{
279
  switch (aFormat) {
280
    case FORMAT_U8:     return "unsigned 8 bit";
281
    case FORMAT_S16:    return "signed 16 bit";
282
    case FORMAT_S24:    return "signed 24 bit MSB";
283
    case FORMAT_S24LSB: return "signed 24 bit LSB";
284
    case FORMAT_S32:    return "signed 32 bit";
285
    case FORMAT_FLT:    return "32 bit floating point";
286
    case FORMAT_NONE:   return "none";
287
    default:            return "unknown";
288
  }
289
}
290
/* static */ uint32_t
291
AudioConfig::SampleSize(AudioConfig::SampleFormat aFormat)
292
0
{
293
0
  switch (aFormat) {
294
0
    case FORMAT_U8:     return 1;
295
0
    case FORMAT_S16:    return 2;
296
0
    case FORMAT_S24:    MOZ_FALLTHROUGH;
297
0
    case FORMAT_S24LSB: MOZ_FALLTHROUGH;
298
0
    case FORMAT_S32:    MOZ_FALLTHROUGH;
299
0
    case FORMAT_FLT:    return 4;
300
0
    case FORMAT_NONE:
301
0
    default:            return 0;
302
0
  }
303
0
}
304
305
/* static */ uint32_t
306
AudioConfig::FormatToBits(AudioConfig::SampleFormat aFormat)
307
0
{
308
0
  switch (aFormat) {
309
0
    case FORMAT_U8:     return 8;
310
0
    case FORMAT_S16:    return 16;
311
0
    case FORMAT_S24LSB: MOZ_FALLTHROUGH;
312
0
    case FORMAT_S24:    return 24;
313
0
    case FORMAT_S32:    MOZ_FALLTHROUGH;
314
0
    case FORMAT_FLT:    return 32;
315
0
    case FORMAT_NONE:   MOZ_FALLTHROUGH;
316
0
    default:            return 0;
317
0
  }
318
0
}
319
320
AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout, uint32_t aRate,
321
                         AudioConfig::SampleFormat aFormat, bool aInterleaved)
322
  : mChannelLayout(aChannelLayout)
323
  , mChannels(aChannelLayout.Count())
324
  , mRate(aRate)
325
  , mFormat(aFormat)
326
  , mInterleaved(aInterleaved)
327
0
{
328
0
}
329
330
AudioConfig::AudioConfig(const ChannelLayout& aChannelLayout,
331
                         uint32_t aChannels,
332
                         uint32_t aRate,
333
                         AudioConfig::SampleFormat aFormat,
334
                         bool aInterleaved)
335
  : mChannelLayout(aChannelLayout)
336
  , mChannels(aChannels)
337
  , mRate(aRate)
338
  , mFormat(aFormat)
339
  , mInterleaved(aInterleaved)
340
0
{
341
0
}
342
343
AudioConfig::AudioConfig(uint32_t aChannels,
344
                         uint32_t aRate,
345
                         AudioConfig::SampleFormat aFormat,
346
                         bool aInterleaved)
347
  : mChannelLayout(aChannels)
348
  , mChannels(aChannels)
349
  , mRate(aRate)
350
  , mFormat(aFormat)
351
  , mInterleaved(aInterleaved)
352
0
{
353
0
}
354
355
} // namespace mozilla