Commit 128d4999 authored by kmackay's avatar kmackay Committed by Commit bot

[Chromecast] Fade in after a mixer input stream has skipped

This reduces audio glitches after a stream has skipped (due to
the stream not having enough data).

BUG= internal b/30747742

Review-Url: https://codereview.chromium.org/2344993003
Cr-Commit-Position: refs/heads/master@{#419084}
parent 77b028cf
......@@ -785,6 +785,7 @@ bool StreamMixerAlsa::TryWriteFrames() {
frames_in_buffer < min_frames_in_buffer) {
// If there has been (or soon will be) an underrun, continue without the
// empty primary input stream.
input->OnSkipped();
continue;
}
......@@ -793,16 +794,13 @@ bool StreamMixerAlsa::TryWriteFrames() {
FROM_HERE, base::TimeDelta::FromMilliseconds(kMinBufferedDataMs / 2),
base::Bind(&StreamMixerAlsa::WriteFrames, base::Unretained(this)));
return false;
} else {
input->OnSkipped();
}
}
if (active_inputs.empty()) {
// No inputs have any data to provide.
if (!inputs_.empty()) {
return false; // If there are some inputs, don't fill with silence.
}
// If we have no inputs, fill with silence to avoid underrun.
// No inputs have any data to provide. Fill with silence to avoid underrun.
chunk_size = kPreventUnderrunChunkSize;
if (!mixed_ || mixed_->frames() < chunk_size) {
mixed_ = ::media::AudioBus::Create(kNumOutputChannels, chunk_size);
......
......@@ -93,6 +93,11 @@ class StreamMixerAlsa {
// MaxReadSize(), and |dest->frames()| shall be >= |frames|.
virtual void GetResampledData(::media::AudioBus* dest, int frames) = 0;
// Called when this input has been skipped for output due to not having any
// data available. This indicates that there will be a gap in the playback
// from this stream.
virtual void OnSkipped() = 0;
// This is called for every InputQueue when the mixer writes data to ALSA
// for any of its input streams.
virtual void AfterWriteFrames(
......
......@@ -235,6 +235,14 @@ void StreamMixerAlsaInputImpl::DidQueueData(bool end_of_stream) {
mixer_->OnFramesQueued();
}
void StreamMixerAlsaInputImpl::OnSkipped() {
DCHECK(mixer_task_runner_->BelongsToCurrentThread());
if (state_ == kStateNormalPlayback) {
// Fade in once this input starts providing data again.
fade_frames_remaining_ = NormalFadeFrames();
}
}
void StreamMixerAlsaInputImpl::AfterWriteFrames(
const MediaPipelineBackendAlsa::RenderingDelay& mixer_rendering_delay) {
DCHECK(mixer_task_runner_->BelongsToCurrentThread());
......
......@@ -120,6 +120,7 @@ class StreamMixerAlsaInputImpl : public StreamMixerAlsa::InputQueue {
mixer_rendering_delay) override;
int MaxReadSize() override;
void GetResampledData(::media::AudioBus* dest, int frames) override;
void OnSkipped() override;
void AfterWriteFrames(const MediaPipelineBackendAlsa::RenderingDelay&
mixer_rendering_delay) override;
void SignalError(StreamMixerAlsaInput::MixerError error) override;
......
......@@ -151,6 +151,7 @@ class MockInputQueue : public StreamMixerAlsa::InputQueue {
mixer_rendering_delay));
int MaxReadSize() override { return max_read_size_; }
MOCK_METHOD2(GetResampledData, void(::media::AudioBus* dest, int frames));
MOCK_METHOD0(OnSkipped, void());
MOCK_METHOD1(AfterWriteFrames,
void(const MediaPipelineBackendAlsa::RenderingDelay&
mixer_rendering_delay));
......@@ -376,6 +377,7 @@ TEST_F(StreamMixerAlsaTest, WriteFrames) {
// to ALSA.
inputs[1]->SetPrimary(false);
inputs[1]->SetMaxReadSize(0);
EXPECT_CALL(*inputs[1], OnSkipped());
inputs[2]->SetPrimary(false);
for (auto* input : inputs) {
if (input != inputs[1])
......@@ -654,6 +656,7 @@ TEST_F(StreamMixerAlsaTest, StuckStreamWithUnderrun) {
EXPECT_CALL(*inputs[0], GetResampledData(_, kNumFrames));
EXPECT_CALL(*inputs[0], AfterWriteFrames(_));
EXPECT_CALL(*inputs[1], GetResampledData(_, _)).Times(0);
EXPECT_CALL(*inputs[1], OnSkipped());
EXPECT_CALL(*inputs[1], AfterWriteFrames(_));
EXPECT_CALL(*mock_alsa(), PcmWritei(_, _, kNumFrames)).Times(1);
......@@ -688,6 +691,7 @@ TEST_F(StreamMixerAlsaTest, StuckStreamWithLowBuffer) {
EXPECT_CALL(*inputs[0], GetResampledData(_, kNumFrames));
EXPECT_CALL(*inputs[0], AfterWriteFrames(_));
EXPECT_CALL(*inputs[1], GetResampledData(_, _)).Times(0);
EXPECT_CALL(*inputs[1], OnSkipped());
EXPECT_CALL(*inputs[1], AfterWriteFrames(_));
EXPECT_CALL(*mock_alsa(), PcmWritei(_, _, kNumFrames)).Times(1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment