1 // This file is part of Desktop App Toolkit,
2 // a set of libraries for developing nice desktop applications.
3 //
4 // For license and copyright information please follow this link:
5 // https://github.com/desktop-app/legal/blob/master/LEGAL
6 //
7 #include "webrtc/details/webrtc_openal_adm.h"
8
9 #include "base/timer.h"
10 #include "base/invoke_queued.h"
11 #include <crl/crl_semaphore.h>
12
13 #undef emit
14 #undef slots
15 #undef signals
16
17 #include "rtc_base/logging.h"
18 #include "rtc_base/thread.h"
19 #include <QtCore/QPointer>
20 #include <QtCore/QThread>
21
22 #ifdef WEBRTC_WIN
23 #include "webrtc/win/webrtc_loopback_adm_win.h"
24 #endif // WEBRTC_WIN
25
26 namespace Webrtc::details {
27 namespace {
28
29 constexpr auto kRecordingFrequency = 48000;
30 constexpr auto kPlayoutFrequency = 48000;
31 constexpr auto kRecordingChannels = 1;
32 constexpr auto kBufferSizeMs = crl::time(10);
33 constexpr auto kPlayoutPart = (kPlayoutFrequency * kBufferSizeMs + 999)
34 / 1000;
35 constexpr auto kRecordingPart = (kRecordingFrequency * kBufferSizeMs + 999)
36 / 1000;
37 constexpr auto kRecordingBufferSize = kRecordingPart * sizeof(int16_t)
38 * kRecordingChannels;
39 constexpr auto kRestartAfterEmptyData = 50; // Half a second with no data.
40 constexpr auto kProcessInterval = crl::time(10);
41
42 constexpr auto kBuffersFullCount = 7;
43 constexpr auto kBuffersKeepReadyCount = 5;
44
45 constexpr auto kDefaultRecordingLatency = crl::time(20);
46 constexpr auto kDefaultPlayoutLatency = crl::time(20);
47 constexpr auto kQueryExactTimeEach = 20;
48
49 constexpr auto kALMaxValues = 6;
50 auto kAL_EVENT_CALLBACK_FUNCTION_SOFT = ALenum();
51 auto kAL_EVENT_CALLBACK_USER_PARAM_SOFT = ALenum();
52 auto kAL_EVENT_TYPE_BUFFER_COMPLETED_SOFT = ALenum();
53 auto kAL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT = ALenum();
54 auto kAL_EVENT_TYPE_DISCONNECTED_SOFT = ALenum();
55 auto kAL_SAMPLE_OFFSET_CLOCK_SOFT = ALenum();
56 auto kAL_SAMPLE_OFFSET_CLOCK_EXACT_SOFT = ALenum();
57
58 auto kALC_DEVICE_LATENCY_SOFT = ALenum();
59
60 using AL_INT64_TYPE = std::int64_t;
61
62 using ALEVENTPROCSOFT = void(*)(
63 ALenum eventType,
64 ALuint object,
65 ALuint param,
66 ALsizei length,
67 const ALchar *message,
68 void *userParam);
69 using ALEVENTCALLBACKSOFT = void(*)(
70 ALEVENTPROCSOFT callback,
71 void *userParam);
72 using ALCSETTHREADCONTEXT = ALCboolean(*)(ALCcontext *context);
73 using ALGETSOURCEI64VSOFT = void(*)(
74 ALuint source,
75 ALenum param,
76 AL_INT64_TYPE *values);
77 using ALCGETINTEGER64VSOFT = void(*)(
78 ALCdevice *device,
79 ALCenum pname,
80 ALsizei size,
81 AL_INT64_TYPE *values);
82
83 ALEVENTCALLBACKSOFT alEventCallbackSOFT/* = nullptr*/;
84 ALCSETTHREADCONTEXT alcSetThreadContext/* = nullptr*/;
85 ALGETSOURCEI64VSOFT alGetSourcei64vSOFT/* = nullptr*/;
86 ALCGETINTEGER64VSOFT alcGetInteger64vSOFT/* = nullptr*/;
87
Failed(ALCdevice * device)88 [[nodiscard]] bool Failed(ALCdevice *device) {
89 if (auto code = alcGetError(device); code != ALC_NO_ERROR) {
90 RTC_LOG(LS_ERROR)
91 << "OpenAL Error "
92 << code
93 << ": "
94 << (const char *)alcGetString(device, code);
95 return true;
96 }
97 return false;
98 }
99
100 template <typename Callback>
EnumerateDevices(ALCenum specifier,Callback && callback)101 void EnumerateDevices(ALCenum specifier, Callback &&callback) {
102 auto devices = alcGetString(nullptr, specifier);
103 Assert(devices != nullptr);
104 while (*devices != 0) {
105 callback(devices);
106 while (*devices != 0) {
107 ++devices;
108 }
109 ++devices;
110 }
111 }
112
DevicesCount(ALCenum specifier)113 [[nodiscard]] int DevicesCount(ALCenum specifier) {
114 auto result = 0;
115 EnumerateDevices(specifier, [&](const char *device) {
116 ++result;
117 });
118 return result;
119 }
120
DeviceName(ALCenum specifier,int index,std::string * name,std::string * guid)121 [[nodiscard]] int DeviceName(
122 ALCenum specifier,
123 int index,
124 std::string *name,
125 std::string *guid) {
126 EnumerateDevices(specifier, [&](const char *device) {
127 if (index < 0) {
128 return;
129 } else if (index > 0) {
130 --index;
131 return;
132 }
133
134 auto string = std::string(device);
135 if (name) {
136 if (guid) {
137 *guid = string;
138 }
139 const auto prefix = std::string("OpenAL Soft on ");
140 if (string.rfind(prefix, 0) == 0) {
141 string = string.substr(prefix.size());
142 }
143 *name = std::move(string);
144 } else if (guid) {
145 *guid = std::move(string);
146 }
147 index = -1;
148 });
149 return (index > 0) ? -1 : 0;
150 }
151
SetStringToArray(const std::string & string,char * array,int size)152 void SetStringToArray(const std::string &string, char *array, int size) {
153 const auto length = std::min(int(string.size()), size - 1);
154 if (length > 0) {
155 memcpy(array, string.data(), length);
156 }
157 array[length] = 0;
158 }
159
DeviceName(ALCenum specifier,int index,char name[webrtc::kAdmMaxDeviceNameSize],char guid[webrtc::kAdmMaxGuidSize])160 [[nodiscard]] int DeviceName(
161 ALCenum specifier,
162 int index,
163 char name[webrtc::kAdmMaxDeviceNameSize],
164 char guid[webrtc::kAdmMaxGuidSize]) {
165 auto sname = std::string();
166 auto sguid = std::string();
167 const auto result = DeviceName(specifier, index, &sname, &sguid);
168 if (result) {
169 return result;
170 }
171 SetStringToArray(sname, name, webrtc::kAdmMaxDeviceNameSize);
172 SetStringToArray(sguid, guid, webrtc::kAdmMaxGuidSize);
173 return 0;
174 }
175
ComputeDefaultDeviceId(ALCenum specifier)176 [[nodiscard]] std::string ComputeDefaultDeviceId(ALCenum specifier) {
177 const auto device = alcGetString(nullptr, specifier);
178 return device ? std::string(device) : std::string();
179 }
180
181 } // namespace
182
183 struct AudioDeviceOpenAL::Data {
DataWebrtc::details::AudioDeviceOpenAL::Data184 Data() : timer(&thread) {
185 context.moveToThread(&thread);
186 }
187
188 QThread thread;
189 QObject context;
190 base::Timer timer;
191
192 QByteArray recordedSamples;
193 int emptyRecordingData = 0;
194 bool recording = false;
195
196 QByteArray playoutSamples;
197 ALuint source = 0;
198 int queuedBuffersCount = 0;
199 std::array<ALuint, kBuffersFullCount> buffers = { { 0 } };
200 std::array<bool, kBuffersFullCount> queuedBuffers = { { false } };
201 int64_t exactDeviceTimeCounter = 0;
202 int64_t lastExactDeviceTime = 0;
203 crl::time lastExactDeviceTimeWhen = 0;
204 bool playing = false;
205 };
206
207 template <typename Callback>
sync(Callback && callback)208 std::invoke_result_t<Callback> AudioDeviceOpenAL::sync(Callback &&callback) {
209 Expects(_data != nullptr);
210
211 using Result = std::invoke_result_t<Callback>;
212
213 crl::semaphore semaphore;
214 if constexpr (std::is_same_v<Result, void>) {
215 InvokeQueued(&_data->context, [&] {
216 callback();
217 semaphore.release();
218 });
219 semaphore.acquire();
220 } else {
221 auto result = Result();
222 InvokeQueued(&_data->context, [&] {
223 result = callback();
224 semaphore.release();
225 });
226 semaphore.acquire();
227 return result;
228 }
229 }
230
AudioDeviceOpenAL(webrtc::TaskQueueFactory * taskQueueFactory)231 AudioDeviceOpenAL::AudioDeviceOpenAL(
232 webrtc::TaskQueueFactory *taskQueueFactory)
233 : _audioDeviceBuffer(taskQueueFactory) {
234 _audioDeviceBuffer.SetRecordingSampleRate(kRecordingFrequency);
235 _audioDeviceBuffer.SetRecordingChannels(kRecordingChannels);
236 }
237
~AudioDeviceOpenAL()238 AudioDeviceOpenAL::~AudioDeviceOpenAL() {
239 Terminate();
240 }
241
ActiveAudioLayer(AudioLayer * audioLayer) const242 int32_t AudioDeviceOpenAL::ActiveAudioLayer(AudioLayer *audioLayer) const {
243 *audioLayer = kPlatformDefaultAudio;
244 return 0;
245 }
246
RegisterAudioCallback(webrtc::AudioTransport * audioCallback)247 int32_t AudioDeviceOpenAL::RegisterAudioCallback(
248 webrtc::AudioTransport *audioCallback) {
249 return _audioDeviceBuffer.RegisterAudioCallback(audioCallback);
250 }
251
Init()252 int32_t AudioDeviceOpenAL::Init() {
253 if (_initialized) {
254 return 0;
255 }
256 alcSetThreadContext = (ALCSETTHREADCONTEXT)alcGetProcAddress(
257 nullptr,
258 "alcSetThreadContext");
259 if (!alcSetThreadContext) {
260 return -1;
261 }
262 alEventCallbackSOFT = (ALEVENTCALLBACKSOFT)alcGetProcAddress(
263 nullptr,
264 "alEventCallbackSOFT");
265
266 alGetSourcei64vSOFT = (ALGETSOURCEI64VSOFT)alcGetProcAddress(
267 nullptr,
268 "alGetSourcei64vSOFT");
269
270 alcGetInteger64vSOFT = (ALCGETINTEGER64VSOFT)alcGetProcAddress(
271 nullptr,
272 "alcGetInteger64vSOFT");
273
274 #define RESOLVE_ENUM(ENUM) k##ENUM = alcGetEnumValue(nullptr, #ENUM)
275 RESOLVE_ENUM(AL_EVENT_CALLBACK_FUNCTION_SOFT);
276 RESOLVE_ENUM(AL_EVENT_CALLBACK_FUNCTION_SOFT);
277 RESOLVE_ENUM(AL_EVENT_CALLBACK_USER_PARAM_SOFT);
278 RESOLVE_ENUM(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT);
279 RESOLVE_ENUM(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT);
280 RESOLVE_ENUM(AL_EVENT_TYPE_DISCONNECTED_SOFT);
281 RESOLVE_ENUM(AL_SAMPLE_OFFSET_CLOCK_SOFT);
282 RESOLVE_ENUM(AL_SAMPLE_OFFSET_CLOCK_EXACT_SOFT);
283 RESOLVE_ENUM(ALC_DEVICE_LATENCY_SOFT);
284 #undef RESOLVE_ENUM
285
286 _initialized = true;
287 return 0;
288 }
289
Terminate()290 int32_t AudioDeviceOpenAL::Terminate() {
291 StopRecording();
292 StopPlayout();
293 _initialized = false;
294
295 Ensures(!_data);
296 return 0;
297 }
298
Initialized() const299 bool AudioDeviceOpenAL::Initialized() const {
300 return _initialized;
301 }
302
InitSpeaker()303 int32_t AudioDeviceOpenAL::InitSpeaker() {
304 _speakerInitialized = true;
305 return 0;
306 }
307
InitMicrophone()308 int32_t AudioDeviceOpenAL::InitMicrophone() {
309 _microphoneInitialized = true;
310 return 0;
311 }
312
SpeakerIsInitialized() const313 bool AudioDeviceOpenAL::SpeakerIsInitialized() const {
314 return _speakerInitialized;
315 }
316
MicrophoneIsInitialized() const317 bool AudioDeviceOpenAL::MicrophoneIsInitialized() const {
318 return _microphoneInitialized;
319 }
320
SpeakerVolumeIsAvailable(bool * available)321 int32_t AudioDeviceOpenAL::SpeakerVolumeIsAvailable(bool *available) {
322 if (available) {
323 *available = false;
324 }
325 return 0;
326 }
327
SetSpeakerVolume(uint32_t volume)328 int32_t AudioDeviceOpenAL::SetSpeakerVolume(uint32_t volume) {
329 return -1;
330 }
331
SpeakerVolume(uint32_t * volume) const332 int32_t AudioDeviceOpenAL::SpeakerVolume(uint32_t *volume) const {
333 return -1;
334 }
335
MaxSpeakerVolume(uint32_t * maxVolume) const336 int32_t AudioDeviceOpenAL::MaxSpeakerVolume(uint32_t *maxVolume) const {
337 return -1;
338 }
339
MinSpeakerVolume(uint32_t * minVolume) const340 int32_t AudioDeviceOpenAL::MinSpeakerVolume(uint32_t *minVolume) const {
341 return -1;
342 }
343
SpeakerMuteIsAvailable(bool * available)344 int32_t AudioDeviceOpenAL::SpeakerMuteIsAvailable(bool *available) {
345 if (available) {
346 *available = false;
347 }
348 return 0;
349 }
350
SetSpeakerMute(bool enable)351 int32_t AudioDeviceOpenAL::SetSpeakerMute(bool enable) {
352 return -1;
353 }
354
SpeakerMute(bool * enabled) const355 int32_t AudioDeviceOpenAL::SpeakerMute(bool *enabled) const {
356 if (enabled) {
357 *enabled = false;
358 }
359 return 0;
360 }
361
MicrophoneMuteIsAvailable(bool * available)362 int32_t AudioDeviceOpenAL::MicrophoneMuteIsAvailable(bool *available) {
363 if (available) {
364 *available = false;
365 }
366 return 0;
367 }
368
SetMicrophoneMute(bool enable)369 int32_t AudioDeviceOpenAL::SetMicrophoneMute(bool enable) {
370 return -1;
371 }
372
MicrophoneMute(bool * enabled) const373 int32_t AudioDeviceOpenAL::MicrophoneMute(bool *enabled) const {
374 if (enabled) {
375 *enabled = false;
376 }
377 return 0;
378 }
379
StereoRecordingIsAvailable(bool * available) const380 int32_t AudioDeviceOpenAL::StereoRecordingIsAvailable(
381 bool *available) const {
382 if (available) {
383 *available = false;
384 }
385 return 0;
386 }
387
SetStereoRecording(bool enable)388 int32_t AudioDeviceOpenAL::SetStereoRecording(bool enable) {
389 return -1;
390 }
391
StereoRecording(bool * enabled) const392 int32_t AudioDeviceOpenAL::StereoRecording(bool *enabled) const {
393 if (enabled) {
394 *enabled = false;
395 }
396 return 0;
397 }
398
StereoPlayoutIsAvailable(bool * available) const399 int32_t AudioDeviceOpenAL::StereoPlayoutIsAvailable(bool *available) const {
400 if (available) {
401 *available = true;
402 }
403 return 0;
404 }
405
SetStereoPlayout(bool enable)406 int32_t AudioDeviceOpenAL::SetStereoPlayout(bool enable) {
407 if (Playing()) {
408 return -1;
409 }
410 _playoutChannels = enable ? 2 : 1;
411 return 0;
412 }
413
StereoPlayout(bool * enabled) const414 int32_t AudioDeviceOpenAL::StereoPlayout(bool *enabled) const {
415 if (enabled) {
416 *enabled = (_playoutChannels == 2);
417 }
418 return 0;
419 }
420
MicrophoneVolumeIsAvailable(bool * available)421 int32_t AudioDeviceOpenAL::MicrophoneVolumeIsAvailable(
422 bool *available) {
423 if (available) {
424 *available = false;
425 }
426 return 0;
427 }
428
SetMicrophoneVolume(uint32_t volume)429 int32_t AudioDeviceOpenAL::SetMicrophoneVolume(uint32_t volume) {
430 return -1;
431 }
432
MicrophoneVolume(uint32_t * volume) const433 int32_t AudioDeviceOpenAL::MicrophoneVolume(uint32_t *volume) const {
434 return -1;
435 }
436
MaxMicrophoneVolume(uint32_t * maxVolume) const437 int32_t AudioDeviceOpenAL::MaxMicrophoneVolume(uint32_t *maxVolume) const {
438 return -1;
439 }
440
MinMicrophoneVolume(uint32_t * minVolume) const441 int32_t AudioDeviceOpenAL::MinMicrophoneVolume(uint32_t *minVolume) const {
442 return -1;
443 }
444
PlayoutDevices()445 int16_t AudioDeviceOpenAL::PlayoutDevices() {
446 return DevicesCount(ALC_ALL_DEVICES_SPECIFIER);
447 }
448
SetPlayoutDevice(uint16_t index)449 int32_t AudioDeviceOpenAL::SetPlayoutDevice(uint16_t index) {
450 const auto result = DeviceName(
451 ALC_ALL_DEVICES_SPECIFIER,
452 index,
453 nullptr,
454 &_playoutDeviceId);
455 return result ? result : restartPlayout();
456 }
457
SetPlayoutDevice(WindowsDeviceType)458 int32_t AudioDeviceOpenAL::SetPlayoutDevice(WindowsDeviceType /*device*/) {
459 _playoutDeviceId = ComputeDefaultDeviceId(ALC_DEFAULT_DEVICE_SPECIFIER);
460 return _playoutDeviceId.empty() ? -1 : restartPlayout();
461 }
462
PlayoutDeviceName(uint16_t index,char name[webrtc::kAdmMaxDeviceNameSize],char guid[webrtc::kAdmMaxGuidSize])463 int32_t AudioDeviceOpenAL::PlayoutDeviceName(
464 uint16_t index,
465 char name[webrtc::kAdmMaxDeviceNameSize],
466 char guid[webrtc::kAdmMaxGuidSize]) {
467 return DeviceName(ALC_ALL_DEVICES_SPECIFIER, index, name, guid);
468 }
469
RecordingDeviceName(uint16_t index,char name[webrtc::kAdmMaxDeviceNameSize],char guid[webrtc::kAdmMaxGuidSize])470 int32_t AudioDeviceOpenAL::RecordingDeviceName(
471 uint16_t index,
472 char name[webrtc::kAdmMaxDeviceNameSize],
473 char guid[webrtc::kAdmMaxGuidSize]) {
474 return DeviceName(ALC_CAPTURE_DEVICE_SPECIFIER, index, name, guid);
475 }
476
RecordingDevices()477 int16_t AudioDeviceOpenAL::RecordingDevices() {
478 return DevicesCount(ALC_CAPTURE_DEVICE_SPECIFIER);
479 }
480
SetRecordingDevice(uint16_t index)481 int32_t AudioDeviceOpenAL::SetRecordingDevice(uint16_t index) {
482 const auto result = DeviceName(
483 ALC_CAPTURE_DEVICE_SPECIFIER,
484 index,
485 nullptr,
486 &_recordingDeviceId);
487 return result ? result : restartRecording();
488 }
489
SetRecordingDevice(WindowsDeviceType)490 int32_t AudioDeviceOpenAL::SetRecordingDevice(WindowsDeviceType /*device*/) {
491 _recordingDeviceId = ComputeDefaultDeviceId(
492 ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
493 return _recordingDeviceId.empty() ? -1 : restartRecording();
494 }
495
PlayoutIsAvailable(bool * available)496 int32_t AudioDeviceOpenAL::PlayoutIsAvailable(bool *available) {
497 if (available) {
498 *available = true;
499 }
500 return 0;
501 }
502
RecordingIsAvailable(bool * available)503 int32_t AudioDeviceOpenAL::RecordingIsAvailable(bool *available) {
504 if (available) {
505 *available = true;
506 }
507 return 0;
508 }
509
InitPlayout()510 int32_t AudioDeviceOpenAL::InitPlayout() {
511 if (!_initialized) {
512 return -1;
513 } else if (_playoutInitialized) {
514 return 0;
515 }
516 _playoutInitialized = true;
517 ensureThreadStarted();
518 openPlayoutDevice();
519 return 0;
520 }
521
openRecordingDevice()522 void AudioDeviceOpenAL::openRecordingDevice() {
523 if (_recordingDevice || _recordingFailed) {
524 return;
525 }
526 _recordingDevice = alcCaptureOpenDevice(
527 _recordingDeviceId.empty() ? nullptr : _recordingDeviceId.c_str(),
528 kRecordingFrequency,
529 AL_FORMAT_MONO16,
530 kRecordingFrequency / 4);
531 if (!_recordingDevice) {
532 RTC_LOG(LS_ERROR)
533 << "OpenAL Capture Device open failed, deviceID: '"
534 << _recordingDeviceId
535 << "'";
536 _recordingFailed = true;
537 return;
538 }
539 // This does not work for capture devices :(
540 //_context = alcCreateContext(_device, nullptr);
541 // alEventCallbackSOFT([](
542 // ALenum eventType,
543 // ALuint object,
544 // ALuint param,
545 // ALsizei length,
546 // const ALchar *message,
547 // void *that) {
548 // static_cast<AudioInputOpenAL*>(that)->handleEvent(
549 // eventType,
550 // object,
551 // param,
552 // length,
553 // message);
554 // }, this);
555 }
556
openPlayoutDevice()557 void AudioDeviceOpenAL::openPlayoutDevice() {
558 if (_playoutDevice || _playoutFailed) {
559 return;
560 }
561 _playoutDevice = alcOpenDevice(
562 _playoutDeviceId.empty() ? nullptr : _playoutDeviceId.c_str());
563 if (!_playoutDevice) {
564 RTC_LOG(LS_ERROR)
565 << "OpenAL Device open failed, deviceID: '"
566 << _playoutDeviceId
567 << "'";
568 _playoutFailed = true;
569 return;
570 }
571 _playoutContext = alcCreateContext(_playoutDevice, nullptr);
572 if (!_playoutContext) {
573 RTC_LOG(LS_ERROR) << "OpenAL Context create failed.";
574 _playoutFailed = true;
575 closePlayoutDevice();
576 return;
577 }
578 sync([&] {
579 alcSetThreadContext(_playoutContext);
580 if (alEventCallbackSOFT) {
581 alEventCallbackSOFT([](
582 ALenum eventType,
583 ALuint object,
584 ALuint param,
585 ALsizei length,
586 const ALchar *message,
587 void *that) {
588 static_cast<AudioDeviceOpenAL*>(that)->handleEvent(
589 eventType,
590 object,
591 param,
592 length,
593 message);
594 }, this);
595 }
596 });
597 }
598
handleEvent(ALenum eventType,ALuint object,ALuint param,ALsizei length,const ALchar * message)599 void AudioDeviceOpenAL::handleEvent(
600 ALenum eventType,
601 ALuint object,
602 ALuint param,
603 ALsizei length,
604 const ALchar *message) {
605 if (eventType == kAL_EVENT_TYPE_DISCONNECTED_SOFT && _thread) {
606 const auto weak = QPointer<QObject>(&_data->context);
607 _thread->PostTask(RTC_FROM_HERE, [=] {
608 if (weak) {
609 restartRecording();
610 }
611 });
612 }
613 }
614
InitRecording()615 int32_t AudioDeviceOpenAL::InitRecording() {
616 if (!_initialized) {
617 return -1;
618 } else if (_recordingInitialized) {
619 return 0;
620 }
621 _recordingInitialized = true;
622 ensureThreadStarted();
623 openRecordingDevice();
624 _audioDeviceBuffer.SetRecordingSampleRate(kRecordingFrequency);
625 _audioDeviceBuffer.SetRecordingChannels(kRecordingChannels);
626 return 0;
627 }
628
ensureThreadStarted()629 void AudioDeviceOpenAL::ensureThreadStarted() {
630 if (_data) {
631 return;
632 }
633 _thread = rtc::Thread::Current();
634 if (_thread && !_thread->IsOwned()) {
635 _thread->UnwrapCurrent();
636 _thread = nullptr;
637 }
638 // Assert(_thread != nullptr);
639 // Assert(_thread->IsOwned());
640
641 _data = std::make_unique<Data>();
642 _data->timer.setCallback([=] { processData(); });
643 _data->thread.setObjectName("Webrtc OpenAL Thread");
644 _data->thread.start(QThread::TimeCriticalPriority);
645 }
646
processData()647 void AudioDeviceOpenAL::processData() {
648 Expects(_data != nullptr);
649
650 if (_data->playing && !_playoutFailed) {
651 processPlayoutData();
652 }
653 if (_data->recording && !_recordingFailed) {
654 processRecordingData();
655 }
656 }
657
processRecordedPart(bool firstInCycle)658 bool AudioDeviceOpenAL::processRecordedPart(bool firstInCycle) {
659 auto samples = ALint();
660 alcGetIntegerv(_recordingDevice, ALC_CAPTURE_SAMPLES, 1, &samples);
661 if (Failed(_recordingDevice)) {
662 restartRecordingQueued();
663 return false;
664 }
665 if (samples <= 0) {
666 if (firstInCycle) {
667 ++_data->emptyRecordingData;
668 if (_data->emptyRecordingData == kRestartAfterEmptyData) {
669 restartRecordingQueued();
670 }
671 }
672 return false;
673 } else if (samples < kRecordingPart) {
674 // Not enough data for 10ms.
675 return false;
676 }
677
678 _recordingLatency = queryRecordingLatencyMs();
679 //RTC_LOG(LS_ERROR) << "RECORDING LATENCY: " << _recordingLatency << "ms";
680
681 _data->emptyRecordingData = 0;
682 if (_data->recordedSamples.size() < kRecordingBufferSize) {
683 _data->recordedSamples.resize(kRecordingBufferSize);
684 }
685 alcCaptureSamples(
686 _recordingDevice,
687 _data->recordedSamples.data(),
688 kRecordingPart);
689 if (Failed(_recordingDevice)) {
690 restartRecordingQueued();
691 return false;
692 }
693 _audioDeviceBuffer.SetRecordedBuffer(
694 _data->recordedSamples.data(),
695 kRecordingPart);
696 _audioDeviceBuffer.SetVQEData(_playoutLatency, _recordingLatency);
697 _audioDeviceBuffer.DeliverRecordedData();
698 return true;
699 }
700
processRecordingData()701 void AudioDeviceOpenAL::processRecordingData() {
702 for (auto first = true; processRecordedPart(first); first = false) {
703 }
704 }
705
clearProcessedBuffer()706 bool AudioDeviceOpenAL::clearProcessedBuffer() {
707 Expects(_data != nullptr);
708
709 auto processed = ALint(0);
710 alGetSourcei(_data->source, AL_BUFFERS_PROCESSED, &processed);
711 if (processed < 1) {
712 return false;
713 }
714 auto buffer = ALuint(0);
715 alSourceUnqueueBuffers(_data->source, 1, &buffer);
716 for (auto i = 0; i != int(_data->buffers.size()); ++i) {
717 if (_data->buffers[i] == buffer) {
718 _data->queuedBuffers[i] = false;
719 --_data->queuedBuffersCount;
720 return true;
721 }
722 }
723 Unexpected("Processed buffer not found.");
724 }
725
unqueueAllBuffers()726 void AudioDeviceOpenAL::unqueueAllBuffers() {
727 alSourcei(_data->source, AL_BUFFER, AL_NONE);
728 ranges::fill(_data->queuedBuffers, false);
729 _data->queuedBuffersCount = 0;
730 }
731
clearProcessedBuffers()732 void AudioDeviceOpenAL::clearProcessedBuffers() {
733 while (true) {
734 if (!clearProcessedBuffer()) {
735 break;
736 }
737 }
738 }
739
queryRecordingLatencyMs()740 crl::time AudioDeviceOpenAL::queryRecordingLatencyMs() {
741 #ifdef WEBRTC_WIN
742 if (kALC_DEVICE_LATENCY_SOFT
743 && kAL_SAMPLE_OFFSET_CLOCK_EXACT_SOFT) { // Check patched build.
744 auto latency = AL_INT64_TYPE();
745 alcGetInteger64vSOFT(
746 _recordingDevice,
747 kALC_DEVICE_LATENCY_SOFT,
748 1,
749 &latency);
750 return latency / 1'000'000;
751 }
752 #endif // WEBRTC_WIN
753 return kDefaultRecordingLatency;
754 }
755
countExactQueuedMsForLatency(crl::time now,bool playing)756 crl::time AudioDeviceOpenAL::countExactQueuedMsForLatency(
757 crl::time now,
758 bool playing) {
759 auto values = std::array<AL_INT64_TYPE, kALMaxValues>{};
760 auto &sampleOffset = values[0];
761 auto &clockTime = values[1];
762 auto &exactDeviceTime = values[2];
763 const auto countExact = alGetSourcei64vSOFT
764 && kAL_SAMPLE_OFFSET_CLOCK_SOFT
765 && kAL_SAMPLE_OFFSET_CLOCK_EXACT_SOFT;
766 if (countExact) {
767 if (!_data->lastExactDeviceTimeWhen
768 || !(++_data->exactDeviceTimeCounter % kQueryExactTimeEach)) {
769 alGetSourcei64vSOFT(
770 _data->source,
771 kAL_SAMPLE_OFFSET_CLOCK_EXACT_SOFT,
772 values.data());
773 _data->lastExactDeviceTime = exactDeviceTime;
774 _data->lastExactDeviceTimeWhen = now;
775 } else {
776 alGetSourcei64vSOFT(
777 _data->source,
778 kAL_SAMPLE_OFFSET_CLOCK_SOFT,
779 values.data());
780
781 // The exactDeviceTime is in nanoseconds.
782 exactDeviceTime = _data->lastExactDeviceTime
783 + (now - _data->lastExactDeviceTimeWhen) * 1'000'000;
784 }
785 } else {
786 auto offset = ALint(0);
787 alGetSourcei(_data->source, AL_SAMPLE_OFFSET, &offset);
788 sampleOffset = (AL_INT64_TYPE(offset) << 32);
789 }
790
791 const auto queuedSamples = (AL_INT64_TYPE(
792 _data->queuedBuffersCount * kPlayoutPart) << 32);
793 const auto processedInOpenAL = playing ? sampleOffset : queuedSamples;
794 const auto secondsQueuedInDevice = std::max(
795 clockTime - exactDeviceTime,
796 AL_INT64_TYPE(0)
797 ) / 1'000'000'000.;
798 const auto secondsQueuedInOpenAL
799 = (double((queuedSamples - processedInOpenAL) >> (32 - 10))
800 / double(kPlayoutFrequency * (1 << 10)));
801
802 const auto queuedTotal = crl::time(base::SafeRound(
803 (secondsQueuedInDevice + secondsQueuedInOpenAL) * 1'000));
804
805 return countExact
806 ? queuedTotal
807 : std::max(queuedTotal, kDefaultPlayoutLatency);
808 }
809
processPlayoutData()810 void AudioDeviceOpenAL::processPlayoutData() {
811 Expects(_data != nullptr);
812
813 const auto playing = [&] {
814 auto state = ALint(AL_INITIAL);
815 alGetSourcei(_data->source, AL_SOURCE_STATE, &state);
816 return (state == AL_PLAYING);
817 };
818 const auto wasPlaying = playing();
819
820 if (wasPlaying) {
821 clearProcessedBuffers();
822 } else {
823 unqueueAllBuffers();
824 }
825
826 const auto wereQueued = _data->queuedBuffers;
827 while (_data->queuedBuffersCount < kBuffersKeepReadyCount) {
828 const auto available = _audioDeviceBuffer.RequestPlayoutData(
829 kPlayoutPart);
830 if (available == kPlayoutPart) {
831 _audioDeviceBuffer.GetPlayoutData(_data->playoutSamples.data());
832 } else {
833 //ranges::fill(_data->playoutSamples, 0);
834 break;
835 }
836 const auto now = crl::now();
837 _playoutLatency = countExactQueuedMsForLatency(now, wasPlaying);
838 //RTC_LOG(LS_ERROR) << "PLAYOUT LATENCY: " << _playoutLatency << "ms";
839
840 const auto i = ranges::find(_data->queuedBuffers, false);
841 Assert(i != end(_data->queuedBuffers));
842 const auto index = int(i - begin(_data->queuedBuffers));
843 alBufferData(
844 _data->buffers[index],
845 (_playoutChannels == 2) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
846 _data->playoutSamples.data(),
847 _data->playoutSamples.size(),
848 kPlayoutFrequency);
849
850 #ifdef WEBRTC_WIN
851 if (IsLoopbackCaptureActive() && _playoutChannels == 2) {
852 LoopbackCapturePushFarEnd(
853 now + _playoutLatency,
854 _data->playoutSamples,
855 kPlayoutFrequency,
856 _playoutChannels);
857 }
858 #endif // WEBRTC_WIN
859
860 _data->queuedBuffers[index] = true;
861 ++_data->queuedBuffersCount;
862 if (wasPlaying) {
863 alSourceQueueBuffers(
864 _data->source,
865 1,
866 _data->buffers.data() + index);
867 }
868 }
869 if (!_data->queuedBuffersCount) {
870 return;
871 }
872 if (!playing()) {
873 if (wasPlaying) {
874 // While we were queueing buffers the source stopped.
875 // Now we can't unqueue only old buffers, so we unqueue all
876 // of them and then re-queue the ones we queued right now.
877 unqueueAllBuffers();
878 for (auto i = 0; i != int(_data->buffers.size()); ++i) {
879 if (!wereQueued[i] && _data->queuedBuffers[i]) {
880 alSourceQueueBuffers(
881 _data->source,
882 1,
883 _data->buffers.data() + i);
884 }
885 }
886 } else {
887 // We were not playing and had no buffers,
888 // so queue them all at once.
889 alSourceQueueBuffers(
890 _data->source,
891 _data->queuedBuffersCount,
892 _data->buffers.data());
893 }
894 alSourcePlay(_data->source);
895 }
896
897 if (Failed(_playoutDevice)) {
898 _playoutFailed = true;
899 }
900 }
901
StartRecording()902 int32_t AudioDeviceOpenAL::StartRecording() {
903 if (!_recordingInitialized) {
904 return -1;
905 } else if (_data && _data->recording) {
906 return 0;
907 }
908 if (_recordingFailed) {
909 _recordingFailed = false;
910 openRecordingDevice();
911 }
912 _audioDeviceBuffer.StartRecording();
913 startCaptureOnThread();
914 return 0;
915 }
916
startCaptureOnThread()917 void AudioDeviceOpenAL::startCaptureOnThread() {
918 Expects(_data != nullptr);
919
920 sync([&] {
921 _data->recording = true;
922 if (_recordingFailed) {
923 return;
924 }
925 alcCaptureStart(_recordingDevice);
926 if (Failed(_recordingDevice)) {
927 _recordingFailed = true;
928 return;
929 }
930 if (!_data->timer.isActive()) {
931 _data->timer.callEach(kProcessInterval);
932 }
933 });
934 if (_recordingFailed) {
935 closeRecordingDevice();
936 }
937 }
938
stopCaptureOnThread()939 void AudioDeviceOpenAL::stopCaptureOnThread() {
940 Expects(_data != nullptr);
941
942 if (!_data->recording) {
943 return;
944 }
945 sync([&] {
946 _data->recording = false;
947 if (_recordingFailed) {
948 return;
949 }
950 if (!_data->playing) {
951 _data->timer.cancel();
952 }
953 if (_recordingDevice) {
954 alcCaptureStop(_recordingDevice);
955 }
956 });
957 }
958
startPlayingOnThread()959 void AudioDeviceOpenAL::startPlayingOnThread() {
960 Expects(_data != nullptr);
961
962 sync([&] {
963 _data->playing = true;
964 if (_playoutFailed) {
965 return;
966 }
967 ALuint source = 0;
968 alGenSources(1, &source);
969 if (source) {
970 alSourcef(source, AL_PITCH, 1.f);
971 alSource3f(source, AL_POSITION, 0, 0, 0);
972 alSource3f(source, AL_VELOCITY, 0, 0, 0);
973 alSourcei(source, AL_LOOPING, 0);
974 alSourcei(source, AL_SOURCE_RELATIVE, 1);
975 alSourcei(source, AL_ROLLOFF_FACTOR, 0);
976 if (alIsExtensionPresent("AL_SOFT_direct_channels_remix")) {
977 alSourcei(source, alGetEnumValue("AL_DIRECT_CHANNELS_SOFT"), 2);
978 }
979 _data->source = source;
980 alGenBuffers(_data->buffers.size(), _data->buffers.data());
981
982 _data->exactDeviceTimeCounter = 0;
983 _data->lastExactDeviceTime = 0;
984 _data->lastExactDeviceTimeWhen = 0;
985
986 const auto bufferSize = kPlayoutPart * sizeof(int16_t)
987 * _playoutChannels;
988
989 _data->playoutSamples = QByteArray(bufferSize, 0);
990 //for (auto i = 0; i != kBuffersKeepReadyCount; ++i) {
991 // alBufferData(
992 // _data->buffers[i],
993 // AL_FORMAT_STEREO16,
994 // _data->playoutSamples.data(),
995 // _data->playoutSamples.size(),
996 // kPlayoutFrequency);
997 // _data->queuedBuffers[i] = true;
998 //}
999 //_data->queuedBuffersCount = kBuffersKeepReadyCount;
1000 //alSourceQueueBuffers(
1001 // source,
1002 // kBuffersKeepReadyCount,
1003 // _data->buffers.data());
1004 //alSourcePlay(source);
1005
1006 if (!_data->timer.isActive()) {
1007 _data->timer.callEach(kProcessInterval);
1008 }
1009 }
1010 });
1011 }
1012
stopPlayingOnThread()1013 void AudioDeviceOpenAL::stopPlayingOnThread() {
1014 Expects(_data != nullptr);
1015
1016 sync([&] {
1017 const auto guard = gsl::finally([&] {
1018 if (alEventCallbackSOFT) {
1019 alEventCallbackSOFT(nullptr, nullptr);
1020 }
1021 alcSetThreadContext(nullptr);
1022 });
1023 if (!_data->playing) {
1024 return;
1025 }
1026 _data->playing = false;
1027 if (_playoutFailed) {
1028 return;
1029 }
1030 if (!_data->recording) {
1031 _data->timer.cancel();
1032 }
1033 if (_data->source) {
1034 alSourceStop(_data->source);
1035 unqueueAllBuffers();
1036 alDeleteBuffers(_data->buffers.size(), _data->buffers.data());
1037 alDeleteSources(1, &_data->source);
1038 _data->source = 0;
1039 ranges::fill(_data->buffers, ALuint(0));
1040 }
1041 });
1042 }
1043
StopRecording()1044 int32_t AudioDeviceOpenAL::StopRecording() {
1045 if (_data) {
1046 stopCaptureOnThread();
1047 _audioDeviceBuffer.StopRecording();
1048 if (!_data->playing) {
1049 _data->thread.quit();
1050 _data->thread.wait();
1051 _data = nullptr;
1052 }
1053 }
1054 closeRecordingDevice();
1055 _recordingInitialized = false;
1056 return 0;
1057 }
1058
restartRecordingQueued()1059 void AudioDeviceOpenAL::restartRecordingQueued() {
1060 Expects(_data != nullptr);
1061
1062 if (!_thread) {
1063 // We support auto-restarting only when started from rtc::Thread.
1064 return;
1065 }
1066 const auto weak = QPointer<QObject>(&_data->context);
1067 _thread->PostTask(RTC_FROM_HERE, [=] {
1068 if (weak) {
1069 restartRecording();
1070 InvokeQueued(&_data->context, [=] {
1071 _data->emptyRecordingData = 0;
1072 });
1073 }
1074 });
1075 }
1076
restartRecording()1077 int AudioDeviceOpenAL::restartRecording() {
1078 if (!_data || !_data->recording) {
1079 return 0;
1080 }
1081 stopCaptureOnThread();
1082 closeRecordingDevice();
1083 if (!validateRecordingDeviceId()) {
1084 sync([&] {
1085 _data->recording = true;
1086 _recordingFailed = true;
1087 });
1088 return 0;
1089 }
1090 _recordingFailed = false;
1091 openRecordingDevice();
1092 startCaptureOnThread();
1093 return 0;
1094 }
1095
restartPlayoutQueued()1096 void AudioDeviceOpenAL::restartPlayoutQueued() {
1097 Expects(_data != nullptr);
1098
1099 if (!_thread) {
1100 // We support auto-restarting only when started from rtc::Thread.
1101 return;
1102 }
1103 const auto weak = QPointer<QObject>(&_data->context);
1104 _thread->PostTask(RTC_FROM_HERE, [=] {
1105 if (weak) {
1106 restartPlayout();
1107 }
1108 });
1109 }
1110
restartPlayout()1111 int AudioDeviceOpenAL::restartPlayout() {
1112 if (!_data || !_data->playing) {
1113 return 0;
1114 }
1115 stopPlayingOnThread();
1116 closePlayoutDevice();
1117 if (!validatePlayoutDeviceId()) {
1118 sync([&] {
1119 _data->playing = true;
1120 _playoutFailed = true;
1121 });
1122 return 0;
1123 }
1124 _playoutFailed = false;
1125 openPlayoutDevice();
1126 startPlayingOnThread();
1127 return 0;
1128 }
1129
closeRecordingDevice()1130 void AudioDeviceOpenAL::closeRecordingDevice() {
1131 //if (_context) {
1132 // alcDestroyContext(_context);
1133 // _context = nullptr;
1134 //}
1135 if (_recordingDevice) {
1136 alcCaptureCloseDevice(_recordingDevice);
1137 _recordingDevice = nullptr;
1138 }
1139 }
1140
closePlayoutDevice()1141 void AudioDeviceOpenAL::closePlayoutDevice() {
1142 if (_playoutContext) {
1143 alcDestroyContext(_playoutContext);
1144 _playoutContext = nullptr;
1145 }
1146 if (_playoutDevice) {
1147 alcCloseDevice(_playoutDevice);
1148 _playoutDevice = nullptr;
1149 }
1150 }
1151
validateRecordingDeviceId()1152 bool AudioDeviceOpenAL::validateRecordingDeviceId() {
1153 auto valid = false;
1154 EnumerateDevices(ALC_CAPTURE_DEVICE_SPECIFIER, [&](const char *device) {
1155 if (!valid && _recordingDeviceId == std::string(device)) {
1156 valid = true;
1157 }
1158 });
1159 if (valid) {
1160 return true;
1161 }
1162 const auto defaultDeviceId = ComputeDefaultDeviceId(
1163 ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
1164 if (!defaultDeviceId.empty()) {
1165 _recordingDeviceId = defaultDeviceId;
1166 return true;
1167 }
1168 RTC_LOG(LS_ERROR) << "Could not find any OpenAL Capture devices.";
1169 return false;
1170 }
1171
validatePlayoutDeviceId()1172 bool AudioDeviceOpenAL::validatePlayoutDeviceId() {
1173 auto valid = false;
1174 EnumerateDevices(ALC_ALL_DEVICES_SPECIFIER, [&](const char *device) {
1175 if (!valid && _playoutDeviceId == std::string(device)) {
1176 valid = true;
1177 }
1178 });
1179 if (valid) {
1180 return true;
1181 }
1182 const auto defaultDeviceId = ComputeDefaultDeviceId(
1183 ALC_DEFAULT_DEVICE_SPECIFIER);
1184 if (!defaultDeviceId.empty()) {
1185 _playoutDeviceId = defaultDeviceId;
1186 return true;
1187 }
1188 RTC_LOG(LS_ERROR) << "Could not find any OpenAL devices.";
1189 return false;
1190 }
1191
RecordingIsInitialized() const1192 bool AudioDeviceOpenAL::RecordingIsInitialized() const {
1193 return _recordingInitialized;
1194 }
1195
Recording() const1196 bool AudioDeviceOpenAL::Recording() const {
1197 return _data && _data->recording;
1198 }
1199
PlayoutIsInitialized() const1200 bool AudioDeviceOpenAL::PlayoutIsInitialized() const {
1201 return _playoutInitialized;
1202 }
1203
StartPlayout()1204 int32_t AudioDeviceOpenAL::StartPlayout() {
1205 if (!_playoutInitialized) {
1206 return -1;
1207 } else if (Playing()) {
1208 return 0;
1209 }
1210 if (_playoutFailed) {
1211 _playoutFailed = false;
1212 openPlayoutDevice();
1213 }
1214 _audioDeviceBuffer.SetPlayoutSampleRate(kPlayoutFrequency);
1215 _audioDeviceBuffer.SetPlayoutChannels(_playoutChannels);
1216 _audioDeviceBuffer.StartPlayout();
1217 startPlayingOnThread();
1218 return 0;
1219 }
1220
StopPlayout()1221 int32_t AudioDeviceOpenAL::StopPlayout() {
1222 if (_data) {
1223 stopPlayingOnThread();
1224 _audioDeviceBuffer.StopPlayout();
1225 if (!_data->recording) {
1226 _data->thread.quit();
1227 _data->thread.wait();
1228 _data = nullptr;
1229 }
1230 }
1231 closePlayoutDevice();
1232 _playoutInitialized = false;
1233 return 0;
1234 }
1235
PlayoutDelay(uint16_t * delayMS) const1236 int32_t AudioDeviceOpenAL::PlayoutDelay(uint16_t *delayMS) const {
1237 if (delayMS) {
1238 *delayMS = 0;
1239 }
1240 return 0;
1241 }
1242
BuiltInAECIsAvailable() const1243 bool AudioDeviceOpenAL::BuiltInAECIsAvailable() const {
1244 return false;
1245 }
1246
BuiltInAGCIsAvailable() const1247 bool AudioDeviceOpenAL::BuiltInAGCIsAvailable() const {
1248 return false;
1249 }
1250
BuiltInNSIsAvailable() const1251 bool AudioDeviceOpenAL::BuiltInNSIsAvailable() const {
1252 return false;
1253 }
1254
EnableBuiltInAEC(bool enable)1255 int32_t AudioDeviceOpenAL::EnableBuiltInAEC(bool enable) {
1256 return enable ? -1 : 0;
1257 }
1258
EnableBuiltInAGC(bool enable)1259 int32_t AudioDeviceOpenAL::EnableBuiltInAGC(bool enable) {
1260 return enable ? -1 : 0;
1261 }
1262
EnableBuiltInNS(bool enable)1263 int32_t AudioDeviceOpenAL::EnableBuiltInNS(bool enable) {
1264 return enable ? -1 : 0;
1265 }
1266
Playing() const1267 bool AudioDeviceOpenAL::Playing() const {
1268 return _data && _data->playing;
1269 }
1270
1271 } // namespace Webrtc::details
1272