Fixes issue in ADM on Mac OSX when audio is renegotiated

Moved from https://codereview.webrtc.org/3009093002/

TBR=hlundin-webrtc

Bug: webrtc:8041
Change-Id: I33485629a6f1dcb86fd4242468841605e7d8a72a
Reviewed-on: https://webrtc-review.googlesource.com/3440
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Commit-Queue: Henrik Andreassson <henrika@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#19949}
This commit is contained in:
henrika
2017-09-25 16:34:30 +02:00
committed by Commit Bot
parent 3ed32accc2
commit 6b3e1a2bbd
2 changed files with 77 additions and 13 deletions

View File

@ -574,6 +574,52 @@ TEST_F(AudioDeviceTest, StartStopRecording) {
StopRecording();
}
// Tests Init/Stop/Init recording without any registered audio callback.
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=8041 for details
// on why this test is useful.
TEST_F(AudioDeviceTest, InitStopInitRecording) {
SKIP_TEST_IF_NOT(requirements_satisfied());
EXPECT_EQ(0, audio_device()->InitRecording());
EXPECT_TRUE(audio_device()->RecordingIsInitialized());
StopRecording();
EXPECT_EQ(0, audio_device()->InitRecording());
StopRecording();
}
// Tests Init/Stop/Init recording while playout is active.
TEST_F(AudioDeviceTest, InitStopInitRecordingWhilePlaying) {
SKIP_TEST_IF_NOT(requirements_satisfied());
StartPlayout();
EXPECT_EQ(0, audio_device()->InitRecording());
EXPECT_TRUE(audio_device()->RecordingIsInitialized());
StopRecording();
EXPECT_EQ(0, audio_device()->InitRecording());
StopRecording();
StopPlayout();
}
// Tests Init/Stop/Init playout without any registered audio callback.
TEST_F(AudioDeviceTest, InitStopInitPlayout) {
SKIP_TEST_IF_NOT(requirements_satisfied());
EXPECT_EQ(0, audio_device()->InitPlayout());
EXPECT_TRUE(audio_device()->PlayoutIsInitialized());
StopPlayout();
EXPECT_EQ(0, audio_device()->InitPlayout());
StopPlayout();
}
// Tests Init/Stop/Init playout while recording is active.
TEST_F(AudioDeviceTest, InitStopInitPlayoutWhileRecording) {
SKIP_TEST_IF_NOT(requirements_satisfied());
StartRecording();
EXPECT_EQ(0, audio_device()->InitPlayout());
EXPECT_TRUE(audio_device()->PlayoutIsInitialized());
StopPlayout();
EXPECT_EQ(0, audio_device()->InitPlayout());
StopPlayout();
StopRecording();
}
// Start playout and verify that the native audio layer starts asking for real
// audio samples to play out using the NeedMorePlayData() callback.
// Note that we can't add expectations on audio parameters in EXPECT_CALL

View File

@ -971,6 +971,7 @@ int32_t AudioDeviceMac::RecordingIsAvailable(bool& available) {
}
int32_t AudioDeviceMac::InitPlayout() {
LOG(LS_INFO) << "InitPlayout";
rtc::CritScope lock(&_critSect);
if (_playing) {
@ -1106,6 +1107,7 @@ int32_t AudioDeviceMac::InitPlayout() {
}
int32_t AudioDeviceMac::InitRecording() {
LOG(LS_INFO) << "InitRecording";
rtc::CritScope lock(&_critSect);
if (_recording) {
@ -1301,6 +1303,7 @@ int32_t AudioDeviceMac::InitRecording() {
}
int32_t AudioDeviceMac::StartRecording() {
LOG(LS_INFO) << "StartRecording";
rtc::CritScope lock(&_critSect);
if (!_recIsInitialized) {
@ -1337,6 +1340,7 @@ int32_t AudioDeviceMac::StartRecording() {
}
int32_t AudioDeviceMac::StopRecording() {
LOG(LS_INFO) << "StopRecording";
rtc::CritScope lock(&_critSect);
if (!_recIsInitialized) {
@ -1344,11 +1348,10 @@ int32_t AudioDeviceMac::StopRecording() {
}
OSStatus err = noErr;
// Stop device
int32_t captureDeviceIsAlive = AtomicGet32(&_captureDeviceIsAlive);
if (_twoDevices) {
if (_recording && captureDeviceIsAlive == 1) {
if (_twoDevices && captureDeviceIsAlive == 1) {
// Recording side uses its own dedicated device and IOProc.
if (_recording) {
_recording = false;
_doStopRec = true; // Signal to io proc to stop audio device
_critSect.Leave(); // Cannot be under lock, risk of deadlock
@ -1357,14 +1360,17 @@ int32_t AudioDeviceMac::StopRecording() {
LOG(LS_WARNING)
<< "Timed out stopping the capture IOProc."
<< "We may have failed to detect a device removal.";
WEBRTC_CA_LOG_WARN(AudioDeviceStop(_inputDeviceID, _inDeviceIOProcID));
WEBRTC_CA_LOG_WARN(
AudioDeviceDestroyIOProcID(_inputDeviceID, _inDeviceIOProcID));
AudioDeviceDestroyIOProcID(_inputDeviceID, _inDeviceIOProcID));
}
_critSect.Enter();
_doStopRec = false;
LOG(LS_VERBOSE) << "Recording stopped";
LOG(LS_INFO) << "Recording stopped (input device)";
} else if (_recIsInitialized) {
WEBRTC_CA_LOG_WARN(
AudioDeviceDestroyIOProcID(_inputDeviceID, _inDeviceIOProcID));
LOG(LS_INFO) << "Recording uninitialized (input device)";
}
} else {
// We signal a stop for a shared device even when rendering has
@ -1383,7 +1389,6 @@ int32_t AudioDeviceMac::StopRecording() {
LOG(LS_WARNING)
<< "Timed out stopping the shared IOProc."
<< "We may have failed to detect a device removal.";
// We assume rendering on a shared device has stopped as well if
// the IOProc times out.
WEBRTC_CA_LOG_WARN(AudioDeviceStop(_outputDeviceID, _deviceIOProcID));
@ -1392,7 +1397,11 @@ int32_t AudioDeviceMac::StopRecording() {
}
_critSect.Enter();
_doStop = false;
LOG(LS_VERBOSE) << "Recording stopped (shared)";
LOG(LS_INFO) << "Recording stopped (shared device)";
} else if (_recIsInitialized && !_playing && !_playIsInitialized) {
WEBRTC_CA_LOG_WARN(
AudioDeviceDestroyIOProcID(_outputDeviceID, _deviceIOProcID));
LOG(LS_INFO) << "Recording uninitialized (shared device)";
}
}
@ -1437,6 +1446,7 @@ bool AudioDeviceMac::PlayoutIsInitialized() const {
}
int32_t AudioDeviceMac::StartPlayout() {
LOG(LS_INFO) << "StartPlayout";
rtc::CritScope lock(&_critSect);
if (!_playIsInitialized) {
@ -1463,6 +1473,7 @@ int32_t AudioDeviceMac::StartPlayout() {
}
int32_t AudioDeviceMac::StopPlayout() {
LOG(LS_INFO) << "StopPlayout";
rtc::CritScope lock(&_critSect);
if (!_playIsInitialized) {
@ -1470,7 +1481,6 @@ int32_t AudioDeviceMac::StopPlayout() {
}
OSStatus err = noErr;
int32_t renderDeviceIsAlive = AtomicGet32(&_renderDeviceIsAlive);
if (_playing && renderDeviceIsAlive == 1) {
// We signal a stop for a shared device even when capturing has not
@ -1497,7 +1507,15 @@ int32_t AudioDeviceMac::StopPlayout() {
}
_critSect.Enter();
_doStop = false;
LOG(LS_VERBOSE) << "Playout stopped";
LOG(LS_INFO) << "Playout stopped";
} else if (_twoDevices && _playIsInitialized) {
WEBRTC_CA_LOG_WARN(
AudioDeviceDestroyIOProcID(_outputDeviceID, _deviceIOProcID));
LOG(LS_INFO) << "Playout uninitialized (output device)";
} else if (!_twoDevices && _playIsInitialized && !_recIsInitialized) {
WEBRTC_CA_LOG_WARN(
AudioDeviceDestroyIOProcID(_outputDeviceID, _deviceIOProcID));
LOG(LS_INFO) << "Playout uninitialized (shared device)";
}
// Setting this signal will allow the worker thread to be stopped.
@ -1840,9 +1858,9 @@ int32_t AudioDeviceMac::InitDevice(const uint16_t userDeviceIndex,
0, NULL, &size, devManf));
if (isInput) {
LOG(LS_VERBOSE) << "Input device: " << devManf << " " << devName;
LOG(LS_INFO) << "Input device: " << devManf << " " << devName;
} else {
LOG(LS_VERBOSE) << "Output device: " << devManf << " " << devName;
LOG(LS_INFO) << "Output device: " << devManf << " " << devName;
}
return 0;