summaryrefslogtreecommitdiff
path: root/chromium/media/base/audio_parameters.h
blob: 17643d804c8e06adaacc06bac4754b7954ff62b3 (plain)
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
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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 <string>
#include <vector>

#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_bus.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"
#include "third_party/abseil-cpp/absl/types/optional.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 macro 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
#define PARAMETERS_ALIGNMENT 16
static_assert(AudioBus::kChannelAlignment == PARAMETERS_ALIGNMENT,
              "Audio buffer parameters struct alignment not same as AudioBus");
// ****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(PARAMETERS_ALIGNMENT)
    AudioInputBufferParameters {
  double volume;
  int64_t capture_time_us;  // base::TimeTicks in microseconds.
  uint32_t size;
  uint32_t id;
  bool key_pressed;
};
struct MEDIA_SHMEM_EXPORT ALIGNAS(PARAMETERS_ALIGNMENT)
    AudioOutputBufferParameters {
  int64_t delay_us;            // base::TimeDelta in microseconds.
  int64_t delay_timestamp_us;  // base::TimeTicks in microseconds.
  uint32_t frames_skipped;
  uint32_t bitstream_data_size;
  uint32_t bitstream_frames;
};
#undef PARAMETERS_ALIGNMENT
#if BUILDFLAG(IS_WIN)
#pragma warning(pop)
#endif

static_assert(sizeof(AudioInputBufferParameters) %
                      AudioBus::kChannelAlignment ==
                  0,
              "AudioInputBufferParameters not aligned");
static_assert(sizeof(AudioOutputBufferParameters) %
                      AudioBus::kChannelAlignment ==
                  0,
              "AudioOutputBufferParameters not aligned");

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;
};

// These convenience function safely computes the size required for
// |shared_memory_count| AudioInputBuffers, with enough memory for AudioBus
// data, using |paremeters| (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);

class MEDIA_SHMEM_EXPORT AudioParameters {
 public:
  // TODO(miu): Rename this enum to something that correctly reflects its
  // semantics, such as "TransportScheme."
  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.media
  // GENERATED_JAVA_CLASS_NAME_OVERRIDE: AudioEncodingFormat
  // GENERATED_JAVA_PREFIX_TO_STRIP: AUDIO_
  enum Format {
    AUDIO_FAKE = 0x00,                // Creates a fake AudioOutputStream object
    AUDIO_PCM_LINEAR = 0x01,          // PCM is 'raw' amplitude samples.
    AUDIO_PCM_LOW_LATENCY = 0x02,     // Linear PCM, low latency requested.
    AUDIO_BITSTREAM_AC3 = 0x04,       // Compressed AC3 bitstream.
    AUDIO_BITSTREAM_EAC3 = 0x08,      // Compressed E-AC3 bitstream.
    AUDIO_BITSTREAM_DTS = 0x10,       // Compressed DTS bitstream.
    AUDIO_BITSTREAM_DTS_HD = 0x20,    // Compressed DTS-HD bitstream.
    AUDIO_BITSTREAM_IEC61937 = 0x40,  // Compressed IEC61937 bitstream.
    AUDIO_FORMAT_LAST =
        AUDIO_BITSTREAM_IEC61937,     // 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 = 1 << 6,  // Indicates an echo canceller is
                                           // available that should only
                                           // experimentally be enabled.
    MULTIZONE = 1 << 7,
    AUDIO_PREFETCH = 1 << 8,
  };

  struct HardwareCapabilities {
    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),
          bitstream_formats(0) {}
    HardwareCapabilities(int bitstream_formats)
        : min_frames_per_buffer(0),
          max_frames_per_buffer(0),
          bitstream_formats(bitstream_formats) {}
    HardwareCapabilities()
        : min_frames_per_buffer(0),
          max_frames_per_buffer(0),
          bitstream_formats(0) {}

    // 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;
    int max_frames_per_buffer;
    int bitstream_formats;
  };

  AudioParameters();
  AudioParameters(Format format,
                  ChannelLayout channel_layout,
                  int sample_rate,
                  int frames_per_buffer);
  AudioParameters(Format format,
                  ChannelLayout channel_layout,
                  int sample_rate,
                  int frames_per_buffer,
                  const HardwareCapabilities& hardware_capabilities);

  ~AudioParameters();

  // Re-initializes all members except for |hardware_capabilities_|.
  void Reset(Format format,
             ChannelLayout channel_layout,
             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;

  void set_format(Format format) { format_ = format; }
  Format format() const { return format_; }

  // A setter for channel_layout_ is intentionally excluded.
  ChannelLayout channel_layout() const { return channel_layout_; }

  // The number of channels is usually computed from channel_layout_. Setting
  // this explicitly is only required with CHANNEL_LAYOUT_DISCRETE.
  void set_channels_for_discrete(int channels) {
    DCHECK(channel_layout_ == CHANNEL_LAYOUT_DISCRETE ||
           channels == ChannelLayoutToChannelCount(channel_layout_));
    channels_ = channels;
  }
  int channels() const { return 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_; }

  absl::optional<HardwareCapabilities> hardware_capabilities() const {
    return hardware_capabilities_;
  }

  void set_hardware_capabilities(
      const absl::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::LatencyType latency_tag) {
    latency_tag_ = latency_tag;
  }
  AudioLatency::LatencyType 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.
  ChannelLayout channel_layout_;  // Order of surround sound channels.
  int channels_;                  // Number of channels. Value set based on
                                  // |channel_layout|.
  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::LatencyType latency_tag_;

  // Audio hardware specific parameters, these are treated as read-only and
  // changing them has no effect.
  absl::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_