0

Fix was_unmuted_ in AudioRendererImpl

This CL fixes how the was_unmuted_ property on the AudioRenderImpl is set. For some audio streams (e.g. autoplaying ads), the volume of the media player is set to 1 before the media is muted and played via autoplay. The audio should only be considered as "unmuted" if the volume is set to a non-zero value when the AudioRendererImpl is in a "Playing" state. The comment in pipeline_impl.cc says that "Calling SetVolume() before Initialize() allows renderers to optimize for power by avoiding initialization of audio output until necessary", suggesting that the calls to SetVolume() before the audio is played is expected and required.

Bug: 1192903
Change-Id: Ifcf442ac2a9c35dff1bff2787dfd98d8c464720f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3011843
Commit-Queue: Evan Liu <evliu@google.com>
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#900144}
This commit is contained in:
evliu
2021-07-09 21:03:08 +00:00
committed by Chromium LUCI CQ
parent 455bf8429e
commit 759dea4ac6
3 changed files with 49 additions and 2 deletions

@ -136,7 +136,7 @@ void AudioRendererImpl::StartRendering_Locked() {
lock_.AssertAcquired();
sink_playing_ = true;
was_unmuted_ = was_unmuted_ || volume_ != 0;
base::AutoUnlock auto_unlock(lock_);
if (volume_ || !null_sink_)
sink_->Play();
@ -731,7 +731,13 @@ void AudioRendererImpl::OnWaiting(WaitingReason reason) {
void AudioRendererImpl::SetVolume(float volume) {
DCHECK(task_runner_->BelongsToCurrentThread());
was_unmuted_ = was_unmuted_ || volume != 0;
// Only consider audio as unmuted if the volume is set to a non-zero value
// when the state is kPlaying.
if (state_ == kPlaying) {
was_unmuted_ = was_unmuted_ || volume != 0;
}
if (state_ == kUninitialized || state_ == kInitializing) {
volume_ = volume;
return;

@ -108,6 +108,7 @@ class MEDIA_EXPORT AudioRendererImpl
void OnResume() override;
void SetPlayDelayCBForTesting(PlayDelayCBForTesting cb);
bool was_unmuted_for_testing() const { return was_unmuted_; }
private:
friend class AudioRendererImplTest;

@ -1686,4 +1686,44 @@ TEST_F(AudioRendererImplTest, HighLatencyHint) {
EXPECT_EQ(buffer_playback_threshold().value, high_latency_playback_threshold);
}
TEST_F(AudioRendererImplTest, PlayUnmuted) {
// Setting the volume to a non-zero value does not count as unmuted until the
// audio is played.
EXPECT_EQ(renderer_->was_unmuted_for_testing(), 0);
renderer_->SetVolume(1);
EXPECT_EQ(renderer_->was_unmuted_for_testing(), 0);
Initialize();
Preroll();
StartTicking();
EXPECT_EQ(renderer_->was_unmuted_for_testing(), 1);
}
TEST_F(AudioRendererImplTest, UnmuteWhilePlaying) {
ConfigureWithMockSink(hardware_params_);
EXPECT_CALL(*mock_sink_, SetVolume(0));
renderer_->SetVolume(0);
EXPECT_EQ(renderer_->was_unmuted_for_testing(), 0);
EXPECT_CALL(*mock_sink_, Start());
EXPECT_CALL(*mock_sink_, Play());
Initialize();
Preroll();
StartTicking();
EXPECT_EQ(renderer_->was_unmuted_for_testing(), 0);
EXPECT_CALL(*mock_sink_, SetVolume(1));
renderer_->SetVolume(1);
EXPECT_EQ(renderer_->was_unmuted_for_testing(), 1);
// Muting should pause the sink.
EXPECT_CALL(*mock_sink_, SetVolume(0));
EXPECT_CALL(*mock_sink_, Pause());
renderer_->SetVolume(0);
EXPECT_EQ(renderer_->was_unmuted_for_testing(), 1);
StopTicking();
EXPECT_CALL(*mock_sink_, Stop());
}
} // namespace media