1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
media / base / audio_parameters.h [blame]
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_AUDIO_PARAMETERS_H_
#define MEDIA_BASE_AUDIO_PARAMETERS_H_
#include <stdint.h>
#include <optional>
#include <string>
#include <vector>
#include "base/atomicops.h"
#include "base/compiler_specific.h"
#include "base/numerics/checked_math.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/audio_latency.h"
#include "media/base/audio_point.h"
#include "media/base/channel_layout.h"
#include "media/base/media_shmem_export.h"
#include "media/base/sample_format.h"
namespace media {
// Use a struct-in-struct approach to ensure that we can calculate the required
// size as sizeof(Audio{Input,Output}BufferParameters) + #(bytes in audio
// buffer) without using packing. Also align Audio{Input,Output}BufferParameters
// instead of in Audio{Input,Output}Buffer to be able to calculate size like so.
// Use a constexpr for the alignment value that's the same as
// AudioBus::kChannelAlignment, since MSVC doesn't accept the latter to be used.
#if BUILDFLAG(IS_WIN)
#pragma warning(push)
#pragma warning(disable : 4324) // Disable warning for added padding.
#endif
constexpr int kParametersAlignment = 16;
// ****WARNING****: Do not change the field types or ordering of these fields
// without checking that alignment is correct. The structs may be concurrently
// accessed by both 32bit and 64bit process in shmem. http://crbug.com/781095.
struct MEDIA_SHMEM_EXPORT alignas(kParametersAlignment)
AudioInputBufferParameters {
double volume;
int64_t capture_time_us; // base::TimeTicks in microseconds.
int64_t glitch_duration_us; // base::TimeDelta in microseconds.
uint32_t glitch_count;
uint32_t size;
uint32_t id;
// Intentionally using deprecated Atomic32 instead of std::atomic to keep the
// struct as a trivial type.
// TODO(https://crbug.com/40259737): Switch to atomic_ref once it's available.
base::subtle::Atomic32 has_unread_data;
};
struct MEDIA_SHMEM_EXPORT alignas(kParametersAlignment)
AudioOutputBufferParameters {
int64_t delay_us; // base::TimeDelta in microseconds.
int64_t delay_timestamp_us; // base::TimeTicks in microseconds.
int64_t glitch_duration_us; // base::TimeDelta in microseconds.
uint32_t glitch_count;
uint32_t bitstream_data_size;
uint32_t bitstream_frames;
};
#if BUILDFLAG(IS_WIN)
#pragma warning(pop)
#endif
struct MEDIA_SHMEM_EXPORT AudioInputBuffer {
AudioInputBufferParameters params;
int8_t audio[1];
};
struct MEDIA_SHMEM_EXPORT AudioOutputBuffer {
AudioOutputBufferParameters params;
int8_t audio[1];
};
struct MEDIA_SHMEM_EXPORT AudioRendererAlgorithmParameters {
// The maximum size for the audio buffer.
base::TimeDelta max_capacity;
// The minimum size for the audio buffer.
base::TimeDelta starting_capacity;
// The minimum size for the audio buffer for encrypted streams.
// Set this to be larger than |max_capacity| because the
// performance of encrypted playback is always worse than clear playback, due
// to decryption and potentially IPC overhead. For the context, see
// https://crbug.com/403462, https://crbug.com/718161 and
// https://crbug.com/879970.
base::TimeDelta starting_capacity_for_encrypted;
};
class AudioParameters;
// These convenience function safely computes the size required for
// |shared_memory_count| AudioInputBuffers, with enough memory for AudioBus
// data, using |parameters| (or alternatively |channels| and |frames|). The
// functions not returning a CheckedNumeric will CHECK on overflow.
MEDIA_SHMEM_EXPORT base::CheckedNumeric<uint32_t>
ComputeAudioInputBufferSizeChecked(const AudioParameters& parameters,
uint32_t audio_bus_count);
MEDIA_SHMEM_EXPORT uint32_t
ComputeAudioInputBufferSize(const AudioParameters& parameters,
uint32_t audio_bus_count);
MEDIA_SHMEM_EXPORT uint32_t
ComputeAudioInputBufferSize(int channels, int frames, uint32_t audio_bus_count);
// These convenience functions safely computes the size required for an
// AudioOutputBuffer with enough memory for AudioBus data using |parameters| (or
// alternatively |channels| and |frames|). The functions not returning a
// CheckedNumeric will CHECK on overflow.
MEDIA_SHMEM_EXPORT base::CheckedNumeric<uint32_t>
ComputeAudioOutputBufferSizeChecked(const AudioParameters& parameters);
MEDIA_SHMEM_EXPORT uint32_t
ComputeAudioOutputBufferSize(const AudioParameters& parameters);
MEDIA_SHMEM_EXPORT uint32_t ComputeAudioOutputBufferSize(int channels,
int frames);
// Channel count and ChannelLayout pair, with helper methods to enforce safe
// construction.
class MEDIA_SHMEM_EXPORT ChannelLayoutConfig {
public:
ChannelLayoutConfig(const ChannelLayoutConfig& other);
ChannelLayoutConfig& operator=(const ChannelLayoutConfig& other);
ChannelLayoutConfig();
ChannelLayoutConfig(ChannelLayout channel_layout, int channels);
~ChannelLayoutConfig();
template <ChannelLayout layout>
static ChannelLayoutConfig FromLayout() {
return ChannelLayoutConfig(layout, ChannelLayoutToChannelCount(layout));
}
static ChannelLayoutConfig Mono();
static ChannelLayoutConfig Stereo();
static ChannelLayoutConfig Guess(int channels);
ChannelLayout channel_layout() const { return channel_layout_; }
int channels() const { return channels_; }
private:
ChannelLayout channel_layout_; // Order of surround sound channels.
int channels_; // Number of channels.
};
// For |CHANNEL_LAYOUT_DISCRETE|, we have to explicitly set the number of
// channels, so we need to use the normal constructor.
template <>
ChannelLayoutConfig ChannelLayoutConfig::FromLayout<CHANNEL_LAYOUT_DISCRETE>() =
delete;
class MEDIA_SHMEM_EXPORT AudioParameters {
public:
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.media
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: AudioEncodingFormat
// GENERATED_JAVA_PREFIX_TO_STRIP: AUDIO_
enum Format {
AUDIO_FAKE = 0x000, // Creates a fake AudioOutputStream object
AUDIO_PCM_LINEAR = 0x001, // PCM is 'raw' amplitude samples.
AUDIO_PCM_LOW_LATENCY = 0x002, // Linear PCM, low latency requested.
AUDIO_BITSTREAM_AC3 = 0x004, // Compressed AC3 bitstream.
AUDIO_BITSTREAM_EAC3 = 0x008, // Compressed E-AC3 bitstream.
AUDIO_BITSTREAM_DTS = 0x010, // Compressed DTS bitstream.
AUDIO_BITSTREAM_DTS_HD = 0x020, // Compressed DTS-HD bitstream.
AUDIO_BITSTREAM_DTSX_P2 = 0x040, // Compressed DTSX Profile 2 bitstream.
AUDIO_BITSTREAM_IEC61937 = 0x080, // Compressed IEC61937 bitstream.
AUDIO_BITSTREAM_DTS_HD_MA =
0x100, // Compressed DTS-HD Master Audio bitstream.
AUDIO_FORMAT_LAST =
AUDIO_BITSTREAM_DTS_HD_MA, // Only used for validation of format.
};
enum {
// Telephone quality sample rate, mostly for speech-only audio.
kTelephoneSampleRate = 8000,
// CD sampling rate is 44.1 KHz or conveniently 2x2x3x3x5x5x7x7.
kAudioCDSampleRate = 44100,
};
enum {
// The maxmium number of PCM frames can be decoded out of a compressed
// audio frame, e.g. MP3, AAC, AC-3.
kMaxFramesPerCompressedAudioBuffer = 4096,
};
// Bitmasks to determine whether certain platform (typically hardware) audio
// effects should be enabled.
enum PlatformEffectsMask {
NO_EFFECTS = 0x0,
ECHO_CANCELLER = 1 << 0,
DUCKING = 1 << 1, // Enables ducking if the OS supports it.
// KEYBOARD_MIC used to hold 1 << 2, but has been deprecated.
HOTWORD = 1 << 3,
NOISE_SUPPRESSION = 1 << 4,
AUTOMATIC_GAIN_CONTROL = 1 << 5,
// EXPERIMENTAL_ECHO_CANCELLER used to hold 1 << 6, but has been deprecated.
MULTIZONE = 1 << 7,
AUDIO_PREFETCH = 1 << 8,
ALLOW_DSP_ECHO_CANCELLER = 1 << 9,
ALLOW_DSP_NOISE_SUPPRESSION = 1 << 10,
ALLOW_DSP_AUTOMATIC_GAIN_CONTROL = 1 << 11,
FUCHSIA_RENDER_USAGE_BACKGROUND = 1 << 12,
FUCHSIA_RENDER_USAGE_MEDIA = 1 << 13,
FUCHSIA_RENDER_USAGE_INTERRUPTION = 1 << 14,
FUCHSIA_RENDER_USAGE_SYSTEM_AGENT = 1 << 15,
FUCHSIA_RENDER_USAGE_COMMUNICATION = 1 << 16,
IGNORE_UI_GAINS = 1 << 17,
VOICE_ISOLATION_SUPPORTED = 1 << 18, // Set when system voice isolation is
// supported.
CLIENT_CONTROLLED_VOICE_ISOLATION =
1 << 19, // Set when client forces to
// enable/disable the platform voice
// isolation effects. False indicates
// to use platform default state.
VOICE_ISOLATION = 1 << 20, // Enable/Disable platform voice isolation.
// Only meaningful when
// CLIENT_CONTROLLED_VOICE_ISOLATION is set.
};
struct HardwareCapabilities {
HardwareCapabilities(int min_frames_per_buffer,
int max_frames_per_buffer,
int default_frames_per_buffer,
bool require_offload)
: min_frames_per_buffer(min_frames_per_buffer),
max_frames_per_buffer(max_frames_per_buffer),
default_frames_per_buffer(default_frames_per_buffer),
require_audio_offload(require_offload) {}
HardwareCapabilities(int min_frames_per_buffer, int max_frames_per_buffer)
: min_frames_per_buffer(min_frames_per_buffer),
max_frames_per_buffer(max_frames_per_buffer) {}
HardwareCapabilities(int bitstream_formats, bool require_encapsulation)
: bitstream_formats(bitstream_formats),
require_encapsulation(require_encapsulation) {}
HardwareCapabilities() = default;
// Minimum and maximum buffer sizes supported by the audio hardware. Opening
// a device with frames_per_buffer set to a value between min and max should
// result in the audio hardware running close to this buffer size, values
// above or below will be clamped to the min or max by the audio system.
// Either value can be 0 and means that the min or max is not known.
int min_frames_per_buffer = 0;
int max_frames_per_buffer = 0;
// The default buffer size that the device will use when frames_per_buffer
// is not specified. Can be `min_frames_per_buffer`,
// `max_frames_per_buffer`, or a value in between. Can be 0 when the
// default is unknown.
int default_frames_per_buffer = 0;
// Bitstream formats (OR'ed) supported by audio hardware.
int bitstream_formats = 0;
// Bitstream will need to be encapsulated in IEC61937 to be
// passed through to the audio hardware.
bool require_encapsulation = false;
// Require audio processing offload.
bool require_audio_offload = false;
};
AudioParameters();
AudioParameters(Format format,
ChannelLayoutConfig channel_layout_config,
int sample_rate,
int frames_per_buffer);
AudioParameters(Format format,
ChannelLayoutConfig channel_layout_config,
int sample_rate,
int frames_per_buffer,
const HardwareCapabilities& hardware_capabilities);
~AudioParameters();
// Re-initializes all members except for |hardware_capabilities_|.
void Reset(Format format,
ChannelLayoutConfig channel_layout_config,
int sample_rate,
int frames_per_buffer);
// Checks that all values are in the expected range. All limits are specified
// in media::Limits.
bool IsValid() const;
// Returns a human-readable string describing |*this|. For debugging & test
// output only.
std::string AsHumanReadableString() const;
// Returns size of audio buffer in bytes when using |fmt| for samples.
int GetBytesPerBuffer(SampleFormat fmt) const;
// Returns the number of bytes representing a frame of audio when using |fmt|
// for samples.
int GetBytesPerFrame(SampleFormat fmt) const;
// Returns the number of microseconds per frame of audio. Intentionally
// reported as a double to surface of partial microseconds per frame, which
// is common for many sample rates. Failing to account for these nanoseconds
// can lead to audio/video sync drift.
double GetMicrosecondsPerFrame() const;
// Returns the duration of this buffer as calculated from frames_per_buffer()
// and sample_rate().
base::TimeDelta GetBufferDuration() const;
// Comparison with other AudioParams.
bool Equals(const AudioParameters& other) const;
// Return true if |format_| is compressed bitstream.
bool IsBitstreamFormat() const;
bool IsFormatSupportedByHardware(Format format) const;
bool RequireEncapsulation() const;
// Return true if offload is requested.
bool RequireOffload() const;
void set_format(Format format) { format_ = format; }
Format format() const { return format_; }
void SetChannelLayoutConfig(ChannelLayout layout, int channels);
const ChannelLayoutConfig& channel_layout_config() const {
return channel_layout_config_;
}
ChannelLayout channel_layout() const {
return channel_layout_config_.channel_layout();
}
int channels() const { return channel_layout_config_.channels(); }
void set_sample_rate(int sample_rate) { sample_rate_ = sample_rate; }
int sample_rate() const { return sample_rate_; }
void set_frames_per_buffer(int frames_per_buffer) {
frames_per_buffer_ = frames_per_buffer;
}
int frames_per_buffer() const { return frames_per_buffer_; }
std::optional<HardwareCapabilities> hardware_capabilities() const {
return hardware_capabilities_;
}
void set_hardware_capabilities(
const std::optional<HardwareCapabilities>& hwc) {
hardware_capabilities_ = hwc;
}
void set_effects(int effects) { effects_ = effects; }
int effects() const { return effects_; }
void set_mic_positions(const std::vector<Point>& mic_positions) {
mic_positions_ = mic_positions;
}
const std::vector<Point>& mic_positions() const { return mic_positions_; }
void set_latency_tag(AudioLatency::Type latency_tag) {
latency_tag_ = latency_tag;
}
AudioLatency::Type latency_tag() const { return latency_tag_; }
AudioParameters(const AudioParameters&);
AudioParameters& operator=(const AudioParameters&);
// Creates reasonable dummy parameters in case no device is available.
static AudioParameters UnavailableDeviceParams();
private:
Format format_; // Format of the stream.
ChannelLayoutConfig channel_layout_config_; // The channel layout and the
// number of channels.
int sample_rate_; // Sampling frequency/rate.
int frames_per_buffer_; // Number of frames in a buffer.
int effects_; // Bitmask using PlatformEffectsMask.
// Microphone positions using Cartesian coordinates:
// x: the horizontal dimension, with positive to the right from the camera's
// perspective.
// y: the depth dimension, with positive forward from the camera's
// perspective.
// z: the vertical dimension, with positive upwards.
//
// Usually, the center of the microphone array will be treated as the origin
// (often the position of the camera).
//
// An empty vector indicates unknown positions.
std::vector<Point> mic_positions_;
// Optional tag to pass latency info from renderer to browser. Set to
// AudioLatency::LATENCY_COUNT by default, which means "not specified".
AudioLatency::Type latency_tag_;
// Audio hardware specific parameters, these are treated as read-only and
// changing them has no effect.
std::optional<HardwareCapabilities> hardware_capabilities_;
};
// Comparison is useful when AudioParameters is used with std structures.
inline bool operator<(const AudioParameters& a, const AudioParameters& b) {
if (a.format() != b.format())
return a.format() < b.format();
if (a.channels() != b.channels())
return a.channels() < b.channels();
if (a.sample_rate() != b.sample_rate())
return a.sample_rate() < b.sample_rate();
return a.frames_per_buffer() < b.frames_per_buffer();
}
} // namespace media
#endif // MEDIA_BASE_AUDIO_PARAMETERS_H_