Android audio playout now supports non-call media streams.

The default (preferred) stream type for output audio is STREAM_VOICE_CALL since the WebRTC stack is mainly intended for VoIP calls. But if the user wants to run in another mode than COMM mode, we now accept it and change the stream type to STREAM_MUSIC instead. It can e.g. be suitable for applications that does not record audio or if a call shall be casted to a Chromecast device.

The solution is somewhat experimental.

NOTRY=TRUE

BUG=webrtc:4767

Review-Url: https://codereview.webrtc.org/2411263003
Cr-Commit-Position: refs/heads/master@{#14613}
This commit is contained in:
henrika 2016-10-12 08:11:42 -07:00 committed by Commit bot
parent 116ec6da50
commit 872f614111
7 changed files with 65 additions and 3 deletions

View File

@ -524,12 +524,16 @@ class AudioDeviceTest : public ::testing::Test {
audio_device_ = CreateAudioDevice(AudioDeviceModule::kPlatformDefaultAudio);
EXPECT_NE(audio_device_.get(), nullptr);
EXPECT_EQ(0, audio_device_->Init());
// Set audio mode to MODE_IN_COMMUNICATION.
audio_manager()->SetCommunicationMode(true);
playout_parameters_ = audio_manager()->GetPlayoutAudioParameters();
record_parameters_ = audio_manager()->GetRecordAudioParameters();
build_info_.reset(new BuildInfo());
}
virtual ~AudioDeviceTest() {
EXPECT_EQ(0, audio_device_->Terminate());
// Restore audio mode back to MODE_NORMAL.
audio_manager()->SetCommunicationMode(false);
}
int playout_sample_rate() const {

View File

@ -35,6 +35,8 @@ AudioManager::JavaAudioManager::JavaAudioManager(
: audio_manager_(std::move(audio_manager)),
init_(native_reg->GetMethodId("init", "()Z")),
dispose_(native_reg->GetMethodId("dispose", "()V")),
set_communication_mode_(
native_reg->GetMethodId("setCommunicationMode", "(Z)V")),
is_communication_mode_enabled_(
native_reg->GetMethodId("isCommunicationModeEnabled", "()Z")),
is_device_blacklisted_for_open_sles_usage_(
@ -55,6 +57,11 @@ void AudioManager::JavaAudioManager::Close() {
audio_manager_->CallVoidMethod(dispose_);
}
void AudioManager::JavaAudioManager::SetCommunicationMode(bool enable) {
audio_manager_->CallVoidMethod(set_communication_mode_,
static_cast<jboolean>(enable));
}
bool AudioManager::JavaAudioManager::IsCommunicationModeEnabled() {
return audio_manager_->CallBooleanMethod(is_communication_mode_enabled_);
}
@ -176,6 +183,12 @@ bool AudioManager::Close() {
return true;
}
void AudioManager::SetCommunicationMode(bool enable) {
ALOGD("SetCommunicationMode(%d)", enable);
RTC_DCHECK(thread_checker_.CalledOnValidThread());
j_audio_manager_->SetCommunicationMode(enable);
}
bool AudioManager::IsCommunicationModeEnabled() const {
ALOGD("IsCommunicationModeEnabled()");
RTC_DCHECK(thread_checker_.CalledOnValidThread());

View File

@ -47,6 +47,7 @@ class AudioManager {
bool Init();
void Close();
void SetCommunicationMode(bool enable);
bool IsCommunicationModeEnabled();
bool IsDeviceBlacklistedForOpenSLESUsage();
@ -54,6 +55,7 @@ class AudioManager {
std::unique_ptr<GlobalRef> audio_manager_;
jmethodID init_;
jmethodID dispose_;
jmethodID set_communication_mode_;
jmethodID is_communication_mode_enabled_;
jmethodID is_device_blacklisted_for_open_sles_usage_;
};
@ -82,6 +84,9 @@ class AudioManager {
// Revert any setting done by Init().
bool Close();
// Set audio mode to AudioManager.MODE_IN_COMMUNICATION if |enable| is true
// and AudioManager.MODE_NORMAL otherwise.
void SetCommunicationMode(bool enable);
// Returns true if current audio mode is AudioManager.MODE_IN_COMMUNICATION.
bool IsCommunicationModeEnabled() const;

View File

@ -35,6 +35,11 @@ class AudioManagerTest : public ::testing::Test {
record_parameters_ = audio_manager()->GetRecordAudioParameters();
}
virtual ~AudioManagerTest() {
// Always ensure that we restore default/normal mode after the test.
audio_manager()->SetCommunicationMode(false);
}
AudioManager* audio_manager() const { return audio_manager_.get(); }
// A valid audio layer must always be set before calling Init(), hence we
@ -107,6 +112,14 @@ TEST_F(AudioManagerTest, InitClose) {
EXPECT_TRUE(audio_manager()->Close());
}
// Verify communication mode functionality.
TEST_F(AudioManagerTest, CommunicationMode) {
audio_manager()->SetCommunicationMode(true);
EXPECT_TRUE(audio_manager()->IsCommunicationModeEnabled());
audio_manager()->SetCommunicationMode(false);
EXPECT_FALSE(audio_manager()->IsCommunicationModeEnabled());
}
TEST_F(AudioManagerTest, IsAcousticEchoCancelerSupported) {
PRINT("%sAcoustic Echo Canceler support: %s\n", kTag,
audio_manager()->IsAcousticEchoCancelerSupported() ? "Yes" : "No");

View File

@ -172,6 +172,16 @@ public class WebRtcAudioManager {
volumeLogger.stop();
}
private void setCommunicationMode(boolean enable) {
if (enable) {
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
Logging.d(TAG, "audio mode is set to AudioManager.MODE_IN_COMMUNICATION");
} else {
audioManager.setMode(AudioManager.MODE_NORMAL);
Logging.d(TAG, "audio mode is set to AudioManager.MODE_NORMAL");
}
}
private boolean isCommunicationModeEnabled() {
return (audioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION);
}

View File

@ -188,6 +188,17 @@ public class WebRtcAudioTrack {
Logging.e(TAG, "AudioTrack.getMinBufferSize returns an invalid value.");
return false;
}
// The default (preferred) stream type is STREAM_VOICE_CALL since the
// WebRTC stack is mainly intended for VoIP calls.
int streamType = AudioManager.STREAM_VOICE_CALL;
if (audioManager.getMode() != AudioManager.MODE_IN_COMMUNICATION) {
// But if the user wants to run in another mode than COMM mode, we
// accept it and change the stream type to STREAM_MUSIC instead. It can
// e.g. be suitable for applications that do not record audio or if a
// call shall be casted to a Chromecast device.
streamType = AudioManager.STREAM_MUSIC;
Logging.w(TAG, "Using AudioManager.STREAM_MUSIC as stream type.");
}
// Ensure that prevision audio session was stopped correctly before trying
// to create a new AudioTrack.
@ -199,9 +210,8 @@ public class WebRtcAudioTrack {
// Create an AudioTrack object and initialize its associated audio buffer.
// The size of this buffer determines how long an AudioTrack can play
// before running out of data.
audioTrack =
new AudioTrack(AudioManager.STREAM_VOICE_CALL, sampleRate, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSizeInBytes, AudioTrack.MODE_STREAM);
audioTrack = new AudioTrack(streamType, sampleRate, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, minBufferSizeInBytes, AudioTrack.MODE_STREAM);
} catch (IllegalArgumentException e) {
Logging.d(TAG, e.getMessage());
return false;

View File

@ -308,6 +308,13 @@ bool OpenSLESPlayer::CreateAudioPlayer() {
// Set audio player configuration to SL_ANDROID_STREAM_VOICE which
// corresponds to android.media.AudioManager.STREAM_VOICE_CALL.
SLint32 stream_type = SL_ANDROID_STREAM_VOICE;
if (!audio_manager_->IsCommunicationModeEnabled()) {
// But use STREAM_MUSIC if the user for some reason wants to run in a mode
// other than the preferred communication mode.
// SL_ANDROID_STREAM_MEDIA <=> android.media.AudioManager.STREAM_MUSIC.
stream_type = SL_ANDROID_STREAM_MEDIA;
ALOGW("Using non-default stream type SL_ANDROID_STREAM_MEDIA");
}
RETURN_ON_ERROR(
(*player_config)
->SetConfiguration(player_config, SL_ANDROID_KEY_STREAM_TYPE,