summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/sdk/objc/native/src/objc_audio_device.h
blob: fcfe7a6e8bc55cd872af966a8753e2ec94c92c74 (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
/*
 *  Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef SDK_OBJC_NATIVE_SRC_OBJC_AUDIO_DEVICE_H_
#define SDK_OBJC_NATIVE_SRC_OBJC_AUDIO_DEVICE_H_

#include <memory>

#import "components/audio/RTCAudioDevice.h"

#include "modules/audio_device/audio_device_buffer.h"
#include "modules/audio_device/include/audio_device.h"
#include "rtc_base/thread.h"

@class ObjCAudioDeviceDelegate;

namespace webrtc {

class FineAudioBuffer;

namespace objc_adm {

class ObjCAudioDeviceModule : public AudioDeviceModule {
 public:
  explicit ObjCAudioDeviceModule(id<RTC_OBJC_TYPE(RTCAudioDevice)> audio_device);
  ~ObjCAudioDeviceModule() override;

  // Retrieve the currently utilized audio layer
  int32_t ActiveAudioLayer(AudioLayer* audioLayer) const override;

  // Full-duplex transportation of PCM audio
  int32_t RegisterAudioCallback(AudioTransport* audioCallback) override;

  // Main initialization and termination
  int32_t Init() override;
  int32_t Terminate() override;
  bool Initialized() const override;

  // Device enumeration
  int16_t PlayoutDevices() override;
  int16_t RecordingDevices() override;
  int32_t PlayoutDeviceName(uint16_t index,
                            char name[kAdmMaxDeviceNameSize],
                            char guid[kAdmMaxGuidSize]) override;
  int32_t RecordingDeviceName(uint16_t index,
                              char name[kAdmMaxDeviceNameSize],
                              char guid[kAdmMaxGuidSize]) override;

  // Device selection
  int32_t SetPlayoutDevice(uint16_t index) override;
  int32_t SetPlayoutDevice(WindowsDeviceType device) override;
  int32_t SetRecordingDevice(uint16_t index) override;
  int32_t SetRecordingDevice(WindowsDeviceType device) override;

  // Audio transport initialization
  int32_t PlayoutIsAvailable(bool* available) override;
  int32_t InitPlayout() override;
  bool PlayoutIsInitialized() const override;
  int32_t RecordingIsAvailable(bool* available) override;
  int32_t InitRecording() override;
  bool RecordingIsInitialized() const override;

  // Audio transport control
  int32_t StartPlayout() override;
  int32_t StopPlayout() override;
  bool Playing() const override;
  int32_t StartRecording() override;
  int32_t StopRecording() override;
  bool Recording() const override;

  // Audio mixer initialization
  int32_t InitSpeaker() override;
  bool SpeakerIsInitialized() const override;
  int32_t InitMicrophone() override;
  bool MicrophoneIsInitialized() const override;

  // Speaker volume controls
  int32_t SpeakerVolumeIsAvailable(bool* available) override;
  int32_t SetSpeakerVolume(uint32_t volume) override;
  int32_t SpeakerVolume(uint32_t* volume) const override;
  int32_t MaxSpeakerVolume(uint32_t* maxVolume) const override;
  int32_t MinSpeakerVolume(uint32_t* minVolume) const override;

  // Microphone volume controls
  int32_t MicrophoneVolumeIsAvailable(bool* available) override;
  int32_t SetMicrophoneVolume(uint32_t volume) override;
  int32_t MicrophoneVolume(uint32_t* volume) const override;
  int32_t MaxMicrophoneVolume(uint32_t* maxVolume) const override;
  int32_t MinMicrophoneVolume(uint32_t* minVolume) const override;

  // Speaker mute control
  int32_t SpeakerMuteIsAvailable(bool* available) override;
  int32_t SetSpeakerMute(bool enable) override;
  int32_t SpeakerMute(bool* enabled) const override;

  // Microphone mute control
  int32_t MicrophoneMuteIsAvailable(bool* available) override;
  int32_t SetMicrophoneMute(bool enable) override;
  int32_t MicrophoneMute(bool* enabled) const override;

  // Stereo support
  int32_t StereoPlayoutIsAvailable(bool* available) const override;
  int32_t SetStereoPlayout(bool enable) override;
  int32_t StereoPlayout(bool* enabled) const override;
  int32_t StereoRecordingIsAvailable(bool* available) const override;
  int32_t SetStereoRecording(bool enable) override;
  int32_t StereoRecording(bool* enabled) const override;

  // Playout delay
  int32_t PlayoutDelay(uint16_t* delayMS) const override;

  // Only supported on Android.
  bool BuiltInAECIsAvailable() const override;
  bool BuiltInAGCIsAvailable() const override;
  bool BuiltInNSIsAvailable() const override;

  // Enables the built-in audio effects. Only supported on Android.
  int32_t EnableBuiltInAEC(bool enable) override;
  int32_t EnableBuiltInAGC(bool enable) override;
  int32_t EnableBuiltInNS(bool enable) override;

  // Play underrun count. Only supported on Android.
  int32_t GetPlayoutUnderrunCount() const override;

#if defined(WEBRTC_IOS)
  int GetPlayoutAudioParameters(AudioParameters* params) const override;
  int GetRecordAudioParameters(AudioParameters* params) const override;
#endif  // WEBRTC_IOS

 public:
  OSStatus OnDeliverRecordedData(AudioUnitRenderActionFlags* flags,
                                 const AudioTimeStamp* time_stamp,
                                 NSInteger bus_number,
                                 UInt32 num_frames,
                                 const AudioBufferList* io_data,
                                 void* render_context,
                                 RTC_OBJC_TYPE(RTCAudioDeviceRenderRecordedDataBlock) render_block);

  OSStatus OnGetPlayoutData(AudioUnitRenderActionFlags* flags,
                            const AudioTimeStamp* time_stamp,
                            NSInteger bus_number,
                            UInt32 num_frames,
                            AudioBufferList* io_data);

  // Notifies `ObjCAudioDeviceModule` that at least one of the audio input
  // parameters or audio input latency of `RTCAudioDevice` has changed. It necessary to
  // update `record_parameters_` with current audio parameter of `RTCAudioDevice`
  // via `UpdateAudioParameters` and if parameters are actually change then
  // ADB parameters are updated with `UpdateInputAudioDeviceBuffer`. Audio input latency
  // stored in `cached_recording_delay_ms_` is also updated with current latency
  // of `RTCAudioDevice`.
  void HandleAudioInputParametersChange();

  // Same as `HandleAudioInputParametersChange` but should be called when audio output
  // parameters of `RTCAudioDevice` has changed.
  void HandleAudioOutputParametersChange();

  // Notifies `ObjCAudioDeviceModule` about audio input interruption happen due to
  // any reason so `ObjCAudioDeviceModule` is can prepare to restart of audio IO.
  void HandleAudioInputInterrupted();

  // Same as `ObjCAudioDeviceModule` but should be called when audio output
  // is interrupted.
  void HandleAudioOutputInterrupted();

 private:
  // Update our audio parameters if they are different from current device audio parameters
  // Returns true when our parameters are update, false - otherwise.
  // `ObjCAudioDeviceModule` has audio device buffer (ADB) which has audio parameters
  // of playout & recording. The ADB is configured to work with specific sample rate & channel
  // count. `ObjCAudioDeviceModule` stores audio parameters which were used to configure ADB in the
  // fields `playout_parameters_` and `recording_parameters_`.
  // `RTCAudioDevice` protocol has its own audio parameters exposed as individual properties.
  // `RTCAudioDevice` audio parameters might change when playout/recording is already in progress,
  // for example, when device is switched. `RTCAudioDevice` audio parameters must be kept in sync
  // with ADB audio parameters. This method is invoked when `RTCAudioDevice` reports that it's audio
  // parameters (`device_params`) are changed and it detects if there any difference with our
  // current audio parameters (`params`). Our parameters are updated in case of actual change and
  // method returns true. In case of actual change there is follow-up call to either
  // `UpdateOutputAudioDeviceBuffer` or `UpdateInputAudioDeviceBuffer` to apply updated
  // `playout_parameters_` or `recording_parameters_` to ADB.

  bool UpdateAudioParameters(AudioParameters& params, const AudioParameters& device_params);

  // Update our cached audio latency with device latency. Device latency is reported by
  // `RTCAudioDevice` object. Whenever latency is changed, `RTCAudioDevice` is obliged to notify ADM
  // about the change via `HandleAudioInputParametersChange` or `HandleAudioOutputParametersChange`.
  // Current device IO latency is cached in the atomic field and used from audio IO thread
  // to be reported to audio device buffer. It is highly recommended by Apple not to call any
  // ObjC methods from audio IO thread, that is why implementation relies on caching latency
  // into a field and being notified when latency is changed, which is the case when device
  // is switched.
  void UpdateAudioDelay(std::atomic<int>& delay_ms, const NSTimeInterval device_latency);

  // Uses current `playout_parameters_` to inform the audio device buffer (ADB)
  // about our internal audio parameters.
  void UpdateOutputAudioDeviceBuffer();

  // Uses current `record_parameters_` to inform the audio device buffer (ADB)
  // about our internal audio parameters.
  void UpdateInputAudioDeviceBuffer();

 private:
  id<RTC_OBJC_TYPE(RTCAudioDevice)> audio_device_;

  const std::unique_ptr<TaskQueueFactory> task_queue_factory_;

  // AudioDeviceBuffer is a buffer to consume audio recorded by `RTCAudioDevice`
  // and provide audio to be played via `RTCAudioDevice`.
  // Audio PCMs could have different sample rate and channels count, but expected
  // to be in 16-bit integer interleaved linear PCM format.
  // The current parameters ADB configured to work with is stored in field
  // `playout_parameters_` for playout and `record_parameters_` for recording.
  // These parameters and ADB must kept in sync with `RTCAudioDevice` audio parameters.
  std::unique_ptr<AudioDeviceBuffer> audio_device_buffer_;

  // Set to 1 when recording is active and 0 otherwise.
  std::atomic<bool> recording_ = false;

  // Set to 1 when playout is active and 0 otherwise.
  std::atomic<bool> playing_ = false;

  // Stores cached value of `RTCAudioDevice outputLatency` to be used from
  // audio IO thread. Latency is updated on audio output parameters change.
  std::atomic<int> cached_playout_delay_ms_ = 0;

  // Same as `cached_playout_delay_ms_` but for audio input
  std::atomic<int> cached_recording_delay_ms_ = 0;

  // Thread that is initialized audio device module.
  rtc::Thread* thread_;

  // Ensures that methods are called from the same thread as this object is
  // initialized on.
  SequenceChecker thread_checker_;

  // I/O audio thread checker.
  SequenceChecker io_playout_thread_checker_;
  SequenceChecker io_record_thread_checker_;

  bool is_initialized_ RTC_GUARDED_BY(thread_checker_) = false;
  bool is_playout_initialized_ RTC_GUARDED_BY(thread_checker_) = false;
  bool is_recording_initialized_ RTC_GUARDED_BY(thread_checker_) = false;

  // Contains audio parameters (sample rate, #channels, buffer size etc.) for
  // the playout and recording sides.
  AudioParameters playout_parameters_;
  AudioParameters record_parameters_;

  // `FineAudioBuffer` takes an `AudioDeviceBuffer` which delivers audio data
  // in chunks of 10ms. `RTCAudioDevice` might deliver recorded data in
  // chunks which are not 10ms long. `FineAudioBuffer` implements adaptation
  // from undetermined chunk size to 10ms chunks.
  std::unique_ptr<FineAudioBuffer> record_fine_audio_buffer_;

  // Same as `record_fine_audio_buffer_` but for audio output.
  std::unique_ptr<FineAudioBuffer> playout_fine_audio_buffer_;

  // Temporary storage for recorded data.
  rtc::BufferT<int16_t> record_audio_buffer_;

  // Delegate object provided to RTCAudioDevice during initialization
  ObjCAudioDeviceDelegate* audio_device_delegate_;
};

}  // namespace objc_adm

}  // namespace webrtc

#endif  // SDK_OBJC_NATIVE_SRC_OBJC_AUDIO_DEVICE_H_