Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 /* | |
| 2 * Copyright (c) 2017 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 "webrtc/modules/audio_device/include/audio_transport_capture.h" | |
| 12 | |
| 13 namespace webrtc { | |
| 14 | |
| 15 namespace { | |
| 16 | |
| 17 // A wrapper over AudioDeviceModule that registers itself as AudioTransport | |
| 18 // callback and redirects the PCM data to AudioTransportCapture callback. | |
| 19 class ADMWrapper : public AudioDeviceModule, | |
| 20 public AudioTransport { | |
| 21 public: | |
| 22 explicit ADMWrapper( | |
| 23 const int32_t id, | |
| 24 const AudioLayer audio_layer, | |
| 25 AudioTransportCapture* capture_cb) | |
|
the sun
2017/03/21 21:42:50
No need for this extra interface.
| |
| 26 : impl_(AudioDeviceModule::Create(id, audio_layer)), | |
| 27 capture_callback_(capture_cb) { | |
| 28 // Register self as the audio transport callback for underlying ADM impl. | |
| 29 auto res = impl_->RegisterAudioCallback(this); | |
| 30 is_valid_ = (impl_.get() != nullptr) && (res == 0); | |
| 31 } | |
| 32 virtual ~ADMWrapper() { | |
| 33 audio_transport_sink_ = nullptr; | |
| 34 capture_callback_ = nullptr; | |
| 35 } | |
| 36 | |
| 37 bool IsValid() { | |
|
the sun
2017/03/21 21:42:50
When is this useful?
lliuu
2017/03/22 21:26:14
I don't want to end up with the situation where th
| |
| 38 return is_valid_; | |
| 39 } | |
| 40 | |
| 41 // RefCountedObject methods overrides. | |
|
henrika_webrtc
2017/03/23 09:08:52
How are these related to RefCountedObject?
lliuu
2017/03/24 00:12:58
Hi Henrik, AudioDeviceModule inherits from RefCoun
henrika_webrtc
2017/03/29 07:42:14
Don't think you can at this stage but I would like
tommi
2017/03/29 08:44:33
Correct - btw lliuu - AudioDeviceModule inherits f
| |
| 42 int64_t TimeUntilNextProcess() override { | |
| 43 return impl_->TimeUntilNextProcess(); | |
| 44 } | |
| 45 void Process() override { | |
| 46 return impl_->Process(); | |
| 47 } | |
| 48 | |
| 49 // AudioTransport methods overrides. | |
| 50 int32_t RecordedDataIsAvailable( | |
| 51 const void* audioSamples, const size_t nSamples, | |
| 52 const size_t nBytesPerSample, const size_t nChannels, | |
| 53 const uint32_t samplesPerSec, const uint32_t totalDelayMS, | |
| 54 const int32_t clockDrift, const uint32_t currentMicLevel, | |
| 55 const bool keyPressed, uint32_t& newMicLevel) override { | |
| 56 int32_t res = 0; | |
| 57 // Capture PCM data before sending to sink. | |
| 58 if (capture_callback_) { | |
| 59 capture_callback_->CaptureRecordedData(audioSamples, nSamples, | |
|
the sun
2017/03/21 21:42:50
No need for this new interface - just pass the cal
lliuu
2017/03/22 18:50:30
Fredrik, what do you think of adding pure virtual
lliuu
2017/03/22 20:34:37
It also occurred to me that if we're letting the u
lliuu
2017/03/22 21:26:14
I'd like to clarify the last comment: I meant that
the sun
2017/03/28 23:33:45
I see, those are fair points.
| |
| 60 nBytesPerSample, nChannels, | |
| 61 samplesPerSec); | |
| 62 } | |
| 63 | |
| 64 // Send to sink. | |
| 65 if (audio_transport_sink_) { | |
| 66 res = audio_transport_sink_->RecordedDataIsAvailable( | |
| 67 audioSamples, nSamples, nBytesPerSample, | |
| 68 nChannels, samplesPerSec, totalDelayMS, | |
| 69 clockDrift, currentMicLevel, keyPressed, | |
| 70 newMicLevel); | |
| 71 } | |
| 72 | |
| 73 return res; | |
| 74 } | |
| 75 | |
| 76 int32_t NeedMorePlayData(const size_t nSamples, const size_t nBytesPerSample, | |
| 77 const size_t nChannels, const uint32_t samplesPerSec, | |
| 78 void* audioSamples, size_t& nSamplesOut, | |
| 79 int64_t* elapsed_time_ms, | |
| 80 int64_t* ntp_time_ms) override { | |
| 81 int32_t res = 0; | |
| 82 // Request data from sink. | |
|
henrika_webrtc
2017/03/23 09:08:52
How can we request data *from* a sink?
lliuu
2017/03/24 00:12:58
Good point. Here "sink" means the actual sink for
| |
| 83 if (audio_transport_sink_) { | |
| 84 res = audio_transport_sink_->NeedMorePlayData( | |
| 85 nSamples, nBytesPerSample, nChannels, | |
| 86 samplesPerSec, audioSamples, nSamplesOut, | |
| 87 elapsed_time_ms, ntp_time_ms); | |
| 88 } | |
| 89 | |
| 90 // Capture after data requested. | |
| 91 if (capture_callback_) { | |
| 92 capture_callback_->CapturePlayoutData(audioSamples, nSamples, | |
| 93 nBytesPerSample, nChannels, | |
| 94 samplesPerSec); | |
| 95 } | |
| 96 | |
| 97 return res; | |
| 98 } | |
| 99 | |
| 100 void PushCaptureData(int voe_channel, const void* audio_data, | |
| 101 int bits_per_sample, int sample_rate, | |
| 102 size_t number_of_channels, | |
| 103 size_t number_of_frames) override { | |
| 104 if (audio_transport_sink_) { | |
| 105 audio_transport_sink_->PushCaptureData(voe_channel, audio_data, | |
| 106 bits_per_sample, sample_rate, | |
| 107 number_of_channels, | |
| 108 number_of_frames); | |
| 109 } | |
| 110 } | |
| 111 | |
| 112 void PullRenderData(int bits_per_sample, int sample_rate, | |
| 113 size_t number_of_channels, size_t number_of_frames, | |
| 114 void* audio_data, int64_t* elapsed_time_ms, | |
| 115 int64_t* ntp_time_ms) override { | |
| 116 if (audio_transport_sink_) { | |
| 117 audio_transport_sink_->PullRenderData( | |
| 118 bits_per_sample, sample_rate, number_of_channels, | |
| 119 number_of_frames, audio_data, elapsed_time_ms, | |
| 120 ntp_time_ms); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 // Override AudioDeviceModule's RegisterAudioCallback method to remember the | |
| 125 // actual audio transport sink (e.g.: voice engine). | |
| 126 int32_t RegisterAudioCallback(AudioTransport* audioCallback) override { | |
| 127 // Remember the audio callback to forward PCM data | |
| 128 audio_transport_sink_ = audioCallback; | |
|
the sun
2017/03/21 21:42:50
audio_transport_sink_ will need to be protected by
lliuu
2017/03/22 18:50:30
Acknowledged.
lliuu
2017/03/22 21:26:14
Actually could you clarify what is the race condit
the sun
2017/03/28 23:33:45
Right you are. That's the same implicit contract t
| |
| 129 return 0; | |
| 130 } | |
| 131 | |
| 132 // AudioDeviceModule pass through method overrides. | |
| 133 int32_t ActiveAudioLayer(AudioLayer* audioLayer) const override { | |
| 134 return impl_->ActiveAudioLayer(audioLayer); | |
| 135 } | |
| 136 ErrorCode LastError() const override { | |
| 137 return impl_->LastError(); | |
| 138 } | |
| 139 int32_t RegisterEventObserver(AudioDeviceObserver* eventCallback) override { | |
| 140 return impl_->RegisterEventObserver(eventCallback); | |
| 141 } | |
| 142 int32_t Init() override { | |
| 143 return impl_->Init(); | |
| 144 } | |
| 145 int32_t Terminate() override { | |
| 146 return impl_->Terminate(); | |
| 147 } | |
| 148 bool Initialized() const override { | |
| 149 return impl_->Initialized(); | |
| 150 } | |
| 151 int16_t PlayoutDevices() override { | |
| 152 return impl_->PlayoutDevices(); | |
| 153 } | |
| 154 int16_t RecordingDevices() override { | |
| 155 return impl_->RecordingDevices(); | |
| 156 } | |
| 157 int32_t PlayoutDeviceName(uint16_t index, | |
| 158 char name[kAdmMaxDeviceNameSize], | |
| 159 char guid[kAdmMaxGuidSize]) override { | |
| 160 return impl_->PlayoutDeviceName(index, name, guid); | |
| 161 } | |
| 162 int32_t RecordingDeviceName(uint16_t index, | |
| 163 char name[kAdmMaxDeviceNameSize], | |
| 164 char guid[kAdmMaxGuidSize]) override { | |
| 165 return impl_->RecordingDeviceName(index, name, guid); | |
| 166 } | |
| 167 int32_t SetPlayoutDevice(uint16_t index) override { | |
| 168 return impl_->SetPlayoutDevice(index); | |
| 169 } | |
| 170 int32_t SetPlayoutDevice(WindowsDeviceType device) override { | |
| 171 return impl_->SetPlayoutDevice(device); | |
| 172 } | |
| 173 int32_t SetRecordingDevice(uint16_t index) override { | |
| 174 return impl_->SetRecordingDevice(index); | |
| 175 } | |
| 176 int32_t SetRecordingDevice(WindowsDeviceType device) override { | |
| 177 return impl_->SetRecordingDevice(device); | |
| 178 } | |
| 179 int32_t PlayoutIsAvailable(bool* available) override { | |
| 180 return impl_->PlayoutIsAvailable(available); | |
| 181 } | |
| 182 int32_t InitPlayout() override { | |
| 183 return impl_->InitPlayout(); | |
| 184 } | |
| 185 bool PlayoutIsInitialized() const override { | |
| 186 return impl_->PlayoutIsInitialized(); | |
| 187 } | |
| 188 int32_t RecordingIsAvailable(bool* available) override { | |
| 189 return impl_->RecordingIsAvailable(available); | |
| 190 } | |
| 191 int32_t InitRecording() override { | |
| 192 return impl_->InitRecording(); | |
| 193 } | |
| 194 bool RecordingIsInitialized() const override { | |
| 195 return impl_->RecordingIsInitialized(); | |
| 196 } | |
| 197 int32_t StartPlayout() override { | |
| 198 return impl_->StartPlayout(); | |
| 199 } | |
| 200 int32_t StopPlayout() override { | |
| 201 return impl_->StopPlayout(); | |
| 202 } | |
| 203 bool Playing() const override { | |
| 204 return impl_->Playing(); | |
| 205 } | |
| 206 int32_t StartRecording() override { | |
| 207 return impl_->StartRecording(); | |
| 208 } | |
| 209 int32_t StopRecording() override { | |
| 210 return impl_->StopRecording(); | |
| 211 } | |
| 212 bool Recording() const override { | |
| 213 return impl_->Recording(); | |
| 214 } | |
| 215 int32_t SetAGC(bool enable) override { | |
| 216 return impl_->SetAGC(enable); | |
| 217 } | |
| 218 bool AGC() const override { | |
| 219 return impl_->AGC(); | |
| 220 } | |
| 221 int32_t SetWaveOutVolume(uint16_t volumeLeft, | |
| 222 uint16_t volumeRight) override { | |
| 223 return impl_->SetWaveOutVolume(volumeLeft, volumeRight); | |
| 224 } | |
| 225 int32_t WaveOutVolume(uint16_t* volumeLeft, | |
| 226 uint16_t* volumeRight) const override { | |
| 227 return impl_->WaveOutVolume(volumeLeft, volumeRight); | |
| 228 } | |
| 229 int32_t InitSpeaker() override { | |
| 230 return impl_->InitSpeaker(); | |
| 231 } | |
| 232 bool SpeakerIsInitialized() const override { | |
| 233 return impl_->SpeakerIsInitialized(); | |
| 234 } | |
| 235 int32_t InitMicrophone() override { | |
| 236 return impl_->InitMicrophone(); | |
| 237 } | |
| 238 bool MicrophoneIsInitialized() const override { | |
| 239 return impl_->MicrophoneIsInitialized(); | |
| 240 } | |
| 241 int32_t SpeakerVolumeIsAvailable(bool* available) override { | |
| 242 return impl_->SpeakerVolumeIsAvailable(available); | |
| 243 } | |
| 244 int32_t SetSpeakerVolume(uint32_t volume) override { | |
| 245 return impl_->SetSpeakerVolume(volume); | |
| 246 } | |
| 247 int32_t SpeakerVolume(uint32_t* volume) const override { | |
| 248 return impl_->SpeakerVolume(volume); | |
| 249 } | |
| 250 int32_t MaxSpeakerVolume(uint32_t* maxVolume) const override { | |
| 251 return impl_->MaxSpeakerVolume(maxVolume); | |
| 252 } | |
| 253 int32_t MinSpeakerVolume(uint32_t* minVolume) const override { | |
| 254 return impl_->MinSpeakerVolume(minVolume); | |
| 255 } | |
| 256 int32_t SpeakerVolumeStepSize(uint16_t* stepSize) const override { | |
| 257 return impl_->SpeakerVolumeStepSize(stepSize); | |
| 258 } | |
| 259 int32_t MicrophoneVolumeIsAvailable(bool* available) override { | |
| 260 return impl_->MicrophoneVolumeIsAvailable(available); | |
| 261 } | |
| 262 int32_t SetMicrophoneVolume(uint32_t volume) override { | |
| 263 return impl_->SetMicrophoneVolume(volume); | |
| 264 } | |
| 265 int32_t MicrophoneVolume(uint32_t* volume) const override { | |
| 266 return impl_->MicrophoneVolume(volume); | |
| 267 } | |
| 268 int32_t MaxMicrophoneVolume(uint32_t* maxVolume) const override { | |
| 269 return impl_->MaxMicrophoneVolume(maxVolume); | |
| 270 } | |
| 271 int32_t MinMicrophoneVolume(uint32_t* minVolume) const override { | |
| 272 return impl_->MinMicrophoneVolume(minVolume); | |
| 273 } | |
| 274 int32_t MicrophoneVolumeStepSize(uint16_t* stepSize) const override { | |
| 275 return impl_->MicrophoneVolumeStepSize(stepSize); | |
| 276 } | |
| 277 int32_t SpeakerMuteIsAvailable(bool* available) override { | |
| 278 return impl_->SpeakerMuteIsAvailable(available); | |
| 279 } | |
| 280 int32_t SetSpeakerMute(bool enable) override { | |
| 281 return impl_->SetSpeakerMute(enable); | |
| 282 } | |
| 283 int32_t SpeakerMute(bool* enabled) const override { | |
| 284 return impl_->SpeakerMute(enabled); | |
| 285 } | |
| 286 int32_t MicrophoneMuteIsAvailable(bool* available) override { | |
| 287 return impl_->MicrophoneMuteIsAvailable(available); | |
| 288 } | |
| 289 int32_t SetMicrophoneMute(bool enable) override { | |
| 290 return impl_->SetMicrophoneMute(enable); | |
| 291 } | |
| 292 int32_t MicrophoneMute(bool* enabled) const override { | |
| 293 return impl_->MicrophoneMute(enabled); | |
| 294 } | |
| 295 int32_t MicrophoneBoostIsAvailable(bool* available) override { | |
| 296 return impl_->MicrophoneBoostIsAvailable(available); | |
| 297 } | |
| 298 int32_t SetMicrophoneBoost(bool enable) override { | |
| 299 return impl_->SetMicrophoneBoost(enable); | |
| 300 } | |
| 301 int32_t MicrophoneBoost(bool* enabled) const override { | |
| 302 return impl_->MicrophoneBoost(enabled); | |
| 303 } | |
| 304 int32_t StereoPlayoutIsAvailable(bool* available) const override { | |
| 305 return impl_->StereoPlayoutIsAvailable(available); | |
| 306 } | |
| 307 int32_t SetStereoPlayout(bool enable) override { | |
| 308 return impl_->SetStereoPlayout(enable); | |
| 309 } | |
| 310 int32_t StereoPlayout(bool* enabled) const override { | |
| 311 return impl_->StereoPlayout(enabled); | |
| 312 } | |
| 313 int32_t StereoRecordingIsAvailable(bool* available) const override { | |
| 314 return impl_->StereoRecordingIsAvailable(available); | |
| 315 } | |
| 316 int32_t SetStereoRecording(bool enable) override { | |
| 317 return impl_->SetStereoRecording(enable); | |
| 318 } | |
| 319 int32_t StereoRecording(bool* enabled) const override { | |
| 320 return impl_->StereoRecording(enabled); | |
| 321 } | |
| 322 int32_t SetRecordingChannel(const ChannelType channel) override { | |
| 323 return impl_->SetRecordingChannel(channel); | |
| 324 } | |
| 325 int32_t RecordingChannel(ChannelType* channel) const override { | |
| 326 return impl_->RecordingChannel(channel); | |
| 327 } | |
| 328 int32_t SetPlayoutBuffer(const BufferType type, | |
| 329 uint16_t sizeMS) override { | |
| 330 return impl_->SetPlayoutBuffer(type, sizeMS); | |
| 331 } | |
| 332 int32_t PlayoutBuffer(BufferType* type, uint16_t* sizeMS) const override { | |
| 333 return impl_->PlayoutBuffer(type, sizeMS); | |
| 334 } | |
| 335 int32_t PlayoutDelay(uint16_t* delayMS) const override { | |
| 336 return impl_->PlayoutDelay(delayMS); | |
| 337 } | |
| 338 int32_t RecordingDelay(uint16_t* delayMS) const override { | |
| 339 return impl_->RecordingDelay(delayMS); | |
| 340 } | |
| 341 int32_t CPULoad(uint16_t* load) const override { | |
| 342 return impl_->CPULoad(load); | |
| 343 } | |
| 344 int32_t StartRawOutputFileRecording( | |
| 345 const char pcmFileNameUTF8[kAdmMaxFileNameSize]) override { | |
| 346 return impl_->StartRawOutputFileRecording(pcmFileNameUTF8); | |
| 347 } | |
| 348 int32_t StopRawOutputFileRecording() override { | |
| 349 return impl_->StopRawOutputFileRecording(); | |
| 350 } | |
| 351 int32_t StartRawInputFileRecording( | |
| 352 const char pcmFileNameUTF8[kAdmMaxFileNameSize]) override { | |
| 353 return impl_->StartRawInputFileRecording(pcmFileNameUTF8); | |
| 354 } | |
| 355 int32_t StopRawInputFileRecording() override { | |
| 356 return impl_->StopRawInputFileRecording(); | |
| 357 } | |
| 358 int32_t SetRecordingSampleRate(const uint32_t samplesPerSec) override { | |
| 359 return impl_->SetRecordingSampleRate(samplesPerSec); | |
| 360 } | |
| 361 int32_t RecordingSampleRate(uint32_t* samplesPerSec) const override { | |
| 362 return impl_->RecordingSampleRate(samplesPerSec); | |
| 363 } | |
| 364 int32_t SetPlayoutSampleRate(const uint32_t samplesPerSec) override { | |
| 365 return impl_->SetPlayoutSampleRate(samplesPerSec); | |
| 366 } | |
| 367 int32_t PlayoutSampleRate(uint32_t* samplesPerSec) const override { | |
| 368 return impl_->PlayoutSampleRate(samplesPerSec); | |
| 369 } | |
| 370 int32_t ResetAudioDevice() override { | |
| 371 return impl_->ResetAudioDevice(); | |
| 372 } | |
| 373 int32_t SetLoudspeakerStatus(bool enable) override { | |
| 374 return impl_->SetLoudspeakerStatus(enable); | |
| 375 } | |
| 376 int32_t GetLoudspeakerStatus(bool* enabled) const override { | |
| 377 return impl_->GetLoudspeakerStatus(enabled); | |
| 378 } | |
| 379 bool BuiltInAECIsAvailable() const override { | |
| 380 return impl_->BuiltInAECIsAvailable(); | |
| 381 } | |
| 382 bool BuiltInAGCIsAvailable() const override { | |
| 383 return impl_->BuiltInAGCIsAvailable(); | |
| 384 } | |
| 385 bool BuiltInNSIsAvailable() const override { | |
| 386 return impl_->BuiltInNSIsAvailable(); | |
| 387 } | |
| 388 int32_t EnableBuiltInAEC(bool enable) override { | |
| 389 return impl_->EnableBuiltInAEC(enable); | |
| 390 } | |
| 391 int32_t EnableBuiltInAGC(bool enable) override { | |
| 392 return impl_->EnableBuiltInAGC(enable); | |
| 393 } | |
| 394 int32_t EnableBuiltInNS(bool enable) override { | |
| 395 return impl_->EnableBuiltInNS(enable); | |
| 396 } | |
| 397 // Only supported on iOS. | |
| 398 #if defined(WEBRTC_IOS) | |
| 399 int GetPlayoutAudioParameters(AudioParameters* params) const override { | |
| 400 return impl_->GetPlayoutAudioParameters(params); | |
| 401 } | |
| 402 int GetRecordAudioParameters(AudioParameters* params) const override { | |
| 403 return impl_->GetRecordAudioParameters(params); | |
| 404 } | |
| 405 #endif // WEBRTC_IOS | |
| 406 | |
| 407 protected: | |
| 408 rtc::scoped_refptr<AudioDeviceModule> impl_; | |
| 409 AudioTransportCapture* capture_callback_ = nullptr; | |
| 410 AudioTransport* audio_transport_sink_ = nullptr; | |
| 411 bool is_valid_ = false; | |
| 412 }; | |
| 413 | |
| 414 | |
| 415 } // namespace | |
| 416 | |
| 417 rtc::scoped_refptr<AudioDeviceModule> | |
| 418 CreateAudioDeviceWithTransportCapture( | |
|
the sun
2017/03/21 21:42:50
No need for this create function if we can agree t
lliuu
2017/03/22 18:50:30
AudioDeviceModule inherits from RefCountedModule,
| |
| 419 const int32_t id, | |
| 420 const AudioDeviceModule::AudioLayer audio_layer, | |
| 421 AudioTransportCapture* proc_callback) { | |
| 422 rtc::scoped_refptr<ADMWrapper> | |
| 423 audio_device( | |
| 424 new rtc::RefCountedObject<ADMWrapper>( | |
| 425 id, audio_layer, proc_callback)); | |
| 426 | |
| 427 if (!audio_device->IsValid()) { | |
| 428 return nullptr; | |
| 429 } | |
| 430 | |
| 431 return audio_device; | |
| 432 } | |
| 433 | |
| 434 } // namespace webrtc | |
| OLD | NEW |