Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Unified Diff: media/filters/audio_renderer_impl_unittest.cc

Issue 941633004: Moved renderer implementation from media/filters/ to media/renderers/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed android build Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « media/filters/audio_renderer_impl.cc ('k') | media/filters/default_renderer_factory.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/filters/audio_renderer_impl_unittest.cc
diff --git a/media/filters/audio_renderer_impl_unittest.cc b/media/filters/audio_renderer_impl_unittest.cc
deleted file mode 100644
index 3d8226835d2fb31779fd5612ee36d0f0743268d4..0000000000000000000000000000000000000000
--- a/media/filters/audio_renderer_impl_unittest.cc
+++ /dev/null
@@ -1,747 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/format_macros.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "media/base/audio_buffer_converter.h"
-#include "media/base/audio_hardware_config.h"
-#include "media/base/audio_splicer.h"
-#include "media/base/fake_audio_renderer_sink.h"
-#include "media/base/gmock_callback_support.h"
-#include "media/base/mock_filters.h"
-#include "media/base/test_helpers.h"
-#include "media/filters/audio_renderer_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::base::TimeDelta;
-using ::testing::_;
-using ::testing::Return;
-using ::testing::SaveArg;
-
-namespace media {
-
-namespace {
-
-// Since AudioBufferConverter is used due to different input/output sample
-// rates, define some helper types to differentiate between the two.
-struct InputFrames {
- explicit InputFrames(int value) : value(value) {}
- int value;
-};
-
-struct OutputFrames {
- explicit OutputFrames(int value) : value(value) {}
- int value;
-};
-
-} // namespace
-
-// Constants to specify the type of audio data used.
-static AudioCodec kCodec = kCodecVorbis;
-static SampleFormat kSampleFormat = kSampleFormatPlanarF32;
-static ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
-static int kChannelCount = 2;
-static int kChannels = ChannelLayoutToChannelCount(kChannelLayout);
-
-// Use a different output sample rate so the AudioBufferConverter is invoked.
-static int kInputSamplesPerSecond = 5000;
-static int kOutputSamplesPerSecond = 10000;
-
-ACTION_P(EnterPendingDecoderInitStateAction, test) {
- test->EnterPendingDecoderInitState(arg1);
-}
-
-class AudioRendererImplTest : public ::testing::Test {
- public:
- // Give the decoder some non-garbage media properties.
- AudioRendererImplTest()
- : hardware_config_(AudioParameters(), AudioParameters()),
- demuxer_stream_(DemuxerStream::AUDIO),
- decoder_(new MockAudioDecoder()),
- ended_(false) {
- AudioDecoderConfig audio_config(kCodec,
- kSampleFormat,
- kChannelLayout,
- kInputSamplesPerSecond,
- NULL,
- 0,
- false);
- demuxer_stream_.set_audio_decoder_config(audio_config);
-
- // Used to save callbacks and run them at a later time.
- EXPECT_CALL(*decoder_, Decode(_, _))
- .WillRepeatedly(Invoke(this, &AudioRendererImplTest::DecodeDecoder));
- EXPECT_CALL(*decoder_, Reset(_))
- .WillRepeatedly(Invoke(this, &AudioRendererImplTest::ResetDecoder));
-
- // Mock out demuxer reads.
- EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly(
- RunCallback<0>(DemuxerStream::kOk,
- scoped_refptr<DecoderBuffer>(new DecoderBuffer(0))));
- EXPECT_CALL(demuxer_stream_, SupportsConfigChanges())
- .WillRepeatedly(Return(true));
- AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
- kChannelLayout,
- kOutputSamplesPerSecond,
- SampleFormatToBytesPerChannel(kSampleFormat) * 8,
- 512);
- hardware_config_.UpdateOutputConfig(out_params);
- ScopedVector<AudioDecoder> decoders;
- decoders.push_back(decoder_);
- sink_ = new FakeAudioRendererSink();
- renderer_.reset(new AudioRendererImpl(message_loop_.message_loop_proxy(),
- sink_.get(),
- decoders.Pass(),
- hardware_config_,
- new MediaLog()));
- }
-
- virtual ~AudioRendererImplTest() {
- SCOPED_TRACE("~AudioRendererImplTest()");
- }
-
- void ExpectUnsupportedAudioDecoder() {
- EXPECT_CALL(*decoder_, Initialize(_, _, _))
- .WillOnce(DoAll(SaveArg<2>(&output_cb_),
- RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED)));
- }
-
- MOCK_METHOD1(OnStatistics, void(const PipelineStatistics&));
- MOCK_METHOD1(OnBufferingStateChange, void(BufferingState));
- MOCK_METHOD1(OnError, void(PipelineStatus));
-
- void InitializeRenderer(const PipelineStatusCB& pipeline_status_cb) {
- renderer_->Initialize(
- &demuxer_stream_, pipeline_status_cb, SetDecryptorReadyCB(),
- base::Bind(&AudioRendererImplTest::OnStatistics,
- base::Unretained(this)),
- base::Bind(&AudioRendererImplTest::OnBufferingStateChange,
- base::Unretained(this)),
- base::Bind(&AudioRendererImplTest::OnEnded, base::Unretained(this)),
- base::Bind(&AudioRendererImplTest::OnError, base::Unretained(this)));
- }
-
- void Initialize() {
- EXPECT_CALL(*decoder_, Initialize(_, _, _))
- .WillOnce(DoAll(SaveArg<2>(&output_cb_),
- RunCallback<1>(PIPELINE_OK)));
- InitializeWithStatus(PIPELINE_OK);
-
- next_timestamp_.reset(new AudioTimestampHelper(kInputSamplesPerSecond));
- }
-
- void InitializeWithStatus(PipelineStatus expected) {
- SCOPED_TRACE(base::StringPrintf("InitializeWithStatus(%d)", expected));
-
- WaitableMessageLoopEvent event;
- InitializeRenderer(event.GetPipelineStatusCB());
- event.RunAndWaitForStatus(expected);
-
- // We should have no reads.
- EXPECT_TRUE(decode_cb_.is_null());
- }
-
- void InitializeAndDestroy() {
- EXPECT_CALL(*decoder_, Initialize(_, _, _))
- .WillOnce(RunCallback<1>(PIPELINE_OK));
-
- WaitableMessageLoopEvent event;
- InitializeRenderer(event.GetPipelineStatusCB());
-
- // Destroy the |renderer_| before we let the MessageLoop run, this simulates
- // an interleaving in which we end up destroying the |renderer_| while the
- // OnDecoderSelected callback is in flight.
- renderer_.reset();
- event.RunAndWaitForStatus(PIPELINE_ERROR_ABORT);
- }
-
- void InitializeAndDestroyDuringDecoderInit() {
- EXPECT_CALL(*decoder_, Initialize(_, _, _))
- .WillOnce(EnterPendingDecoderInitStateAction(this));
-
- WaitableMessageLoopEvent event;
- InitializeRenderer(event.GetPipelineStatusCB());
- base::RunLoop().RunUntilIdle();
- DCHECK(!init_decoder_cb_.is_null());
-
- renderer_.reset();
- event.RunAndWaitForStatus(PIPELINE_ERROR_ABORT);
- }
-
- void EnterPendingDecoderInitState(PipelineStatusCB cb) {
- init_decoder_cb_ = cb;
- }
-
- void FlushDuringPendingRead() {
- SCOPED_TRACE("FlushDuringPendingRead()");
- WaitableMessageLoopEvent flush_event;
- renderer_->Flush(flush_event.GetClosure());
- SatisfyPendingRead(InputFrames(256));
- flush_event.RunAndWait();
-
- EXPECT_FALSE(IsReadPending());
- }
-
- void Preroll() {
- Preroll(base::TimeDelta(), base::TimeDelta(), PIPELINE_OK);
- }
-
- void Preroll(base::TimeDelta start_timestamp,
- base::TimeDelta first_timestamp,
- PipelineStatus expected) {
- SCOPED_TRACE(base::StringPrintf("Preroll(%" PRId64 ", %d)",
- first_timestamp.InMilliseconds(),
- expected));
- next_timestamp_->SetBaseTimestamp(first_timestamp);
-
- // Fill entire buffer to complete prerolling.
- renderer_->SetMediaTime(start_timestamp);
- renderer_->StartPlaying();
- WaitForPendingRead();
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
- DeliverRemainingAudio();
- }
-
- void StartTicking() {
- renderer_->StartTicking();
- renderer_->SetPlaybackRate(1.0f);
- }
-
- void StopTicking() { renderer_->StopTicking(); }
-
- bool IsReadPending() const {
- return !decode_cb_.is_null();
- }
-
- void WaitForPendingRead() {
- SCOPED_TRACE("WaitForPendingRead()");
- if (!decode_cb_.is_null())
- return;
-
- DCHECK(wait_for_pending_decode_cb_.is_null());
-
- WaitableMessageLoopEvent event;
- wait_for_pending_decode_cb_ = event.GetClosure();
- event.RunAndWait();
-
- DCHECK(!decode_cb_.is_null());
- DCHECK(wait_for_pending_decode_cb_.is_null());
- }
-
- // Delivers decoded frames to |renderer_|.
- void SatisfyPendingRead(InputFrames frames) {
- CHECK_GT(frames.value, 0);
- CHECK(!decode_cb_.is_null());
-
- scoped_refptr<AudioBuffer> buffer =
- MakeAudioBuffer<float>(kSampleFormat,
- kChannelLayout,
- kChannelCount,
- kInputSamplesPerSecond,
- 1.0f,
- 0.0f,
- frames.value,
- next_timestamp_->GetTimestamp());
- next_timestamp_->AddFrames(frames.value);
-
- DeliverBuffer(AudioDecoder::kOk, buffer);
- }
-
- void DeliverEndOfStream() {
- DCHECK(!decode_cb_.is_null());
-
- // Return EOS buffer to trigger EOS frame.
- EXPECT_CALL(demuxer_stream_, Read(_))
- .WillOnce(RunCallback<0>(DemuxerStream::kOk,
- DecoderBuffer::CreateEOSBuffer()));
-
- // Satify pending |decode_cb_| to trigger a new DemuxerStream::Read().
- message_loop_.PostTask(
- FROM_HERE,
- base::Bind(base::ResetAndReturn(&decode_cb_), AudioDecoder::kOk));
-
- WaitForPendingRead();
-
- message_loop_.PostTask(
- FROM_HERE,
- base::Bind(base::ResetAndReturn(&decode_cb_), AudioDecoder::kOk));
-
- base::RunLoop().RunUntilIdle();
- }
-
- // Delivers frames until |renderer_|'s internal buffer is full and no longer
- // has pending reads.
- void DeliverRemainingAudio() {
- while (frames_remaining_in_buffer().value > 0) {
- SatisfyPendingRead(InputFrames(256));
- }
- }
-
- // Attempts to consume |requested_frames| frames from |renderer_|'s internal
- // buffer. Returns true if and only if all of |requested_frames| were able
- // to be consumed.
- bool ConsumeBufferedData(OutputFrames requested_frames) {
- scoped_ptr<AudioBus> bus =
- AudioBus::Create(kChannels, requested_frames.value);
- int frames_read = 0;
- EXPECT_TRUE(sink_->Render(bus.get(), 0, &frames_read));
- return frames_read == requested_frames.value;
- }
-
- OutputFrames frames_buffered() {
- return OutputFrames(renderer_->algorithm_->frames_buffered());
- }
-
- OutputFrames buffer_capacity() {
- return OutputFrames(renderer_->algorithm_->QueueCapacity());
- }
-
- OutputFrames frames_remaining_in_buffer() {
- // This can happen if too much data was delivered, in which case the buffer
- // will accept the data but not increase capacity.
- if (frames_buffered().value > buffer_capacity().value) {
- return OutputFrames(0);
- }
- return OutputFrames(buffer_capacity().value - frames_buffered().value);
- }
-
- void force_config_change() {
- renderer_->OnConfigChange();
- }
-
- InputFrames converter_input_frames_left() const {
- return InputFrames(
- renderer_->buffer_converter_->input_frames_left_for_testing());
- }
-
- bool splicer_has_next_buffer() const {
- return renderer_->splicer_->HasNextBuffer();
- }
-
- base::TimeDelta CurrentMediaTime() {
- return renderer_->CurrentMediaTime();
- }
-
- bool ended() const { return ended_; }
-
- // Fixture members.
- base::MessageLoop message_loop_;
- scoped_ptr<AudioRendererImpl> renderer_;
- scoped_refptr<FakeAudioRendererSink> sink_;
- AudioHardwareConfig hardware_config_;
-
- private:
- void DecodeDecoder(const scoped_refptr<DecoderBuffer>& buffer,
- const AudioDecoder::DecodeCB& decode_cb) {
- // TODO(scherkus): Make this a DCHECK after threading semantics are fixed.
- if (base::MessageLoop::current() != &message_loop_) {
- message_loop_.PostTask(FROM_HERE, base::Bind(
- &AudioRendererImplTest::DecodeDecoder,
- base::Unretained(this), buffer, decode_cb));
- return;
- }
-
- CHECK(decode_cb_.is_null()) << "Overlapping decodes are not permitted";
- decode_cb_ = decode_cb;
-
- // Wake up WaitForPendingRead() if needed.
- if (!wait_for_pending_decode_cb_.is_null())
- base::ResetAndReturn(&wait_for_pending_decode_cb_).Run();
- }
-
- void ResetDecoder(const base::Closure& reset_cb) {
- if (!decode_cb_.is_null()) {
- // |reset_cb| will be called in DeliverBuffer(), after the decoder is
- // flushed.
- reset_cb_ = reset_cb;
- return;
- }
-
- message_loop_.PostTask(FROM_HERE, reset_cb);
- }
-
- void DeliverBuffer(AudioDecoder::Status status,
- const scoped_refptr<AudioBuffer>& buffer) {
- CHECK(!decode_cb_.is_null());
- if (buffer.get() && !buffer->end_of_stream())
- output_cb_.Run(buffer);
- base::ResetAndReturn(&decode_cb_).Run(status);
-
- if (!reset_cb_.is_null())
- base::ResetAndReturn(&reset_cb_).Run();
-
- base::RunLoop().RunUntilIdle();
- }
-
- void OnEnded() {
- CHECK(!ended_);
- ended_ = true;
- }
-
- MockDemuxerStream demuxer_stream_;
- MockAudioDecoder* decoder_;
-
- // Used for satisfying reads.
- AudioDecoder::OutputCB output_cb_;
- AudioDecoder::DecodeCB decode_cb_;
- base::Closure reset_cb_;
- scoped_ptr<AudioTimestampHelper> next_timestamp_;
-
- // Run during DecodeDecoder() to unblock WaitForPendingRead().
- base::Closure wait_for_pending_decode_cb_;
-
- PipelineStatusCB init_decoder_cb_;
- bool ended_;
-
- DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest);
-};
-
-TEST_F(AudioRendererImplTest, Initialize_Successful) {
- Initialize();
-}
-
-TEST_F(AudioRendererImplTest, Initialize_DecoderInitFailure) {
- ExpectUnsupportedAudioDecoder();
- InitializeWithStatus(DECODER_ERROR_NOT_SUPPORTED);
-}
-
-TEST_F(AudioRendererImplTest, Preroll) {
- Initialize();
- Preroll();
-}
-
-TEST_F(AudioRendererImplTest, StartTicking) {
- Initialize();
- Preroll();
- StartTicking();
-
- // Drain internal buffer, we should have a pending read.
- EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
- WaitForPendingRead();
-}
-
-TEST_F(AudioRendererImplTest, EndOfStream) {
- Initialize();
- Preroll();
- StartTicking();
-
- // Drain internal buffer, we should have a pending read.
- EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
- WaitForPendingRead();
-
- // Forcefully trigger underflow.
- EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1)));
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
-
- // Fulfill the read with an end-of-stream buffer. Doing so should change our
- // buffering state so playback resumes.
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
- DeliverEndOfStream();
-
- // Consume all remaining data. We shouldn't have signal ended yet.
- EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(ended());
-
- // Ended should trigger on next render call.
- EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1)));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(ended());
-}
-
-TEST_F(AudioRendererImplTest, Underflow) {
- Initialize();
- Preroll();
- StartTicking();
-
- // Drain internal buffer, we should have a pending read.
- EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
- WaitForPendingRead();
-
- // Verify the next FillBuffer() call triggers a buffering state change
- // update.
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
- EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1)));
-
- // Verify we're still not getting audio data.
- EXPECT_EQ(0, frames_buffered().value);
- EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1)));
-
- // Deliver enough data to have enough for buffering.
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
- DeliverRemainingAudio();
-
- // Verify we're getting audio data.
- EXPECT_TRUE(ConsumeBufferedData(OutputFrames(1)));
-}
-
-TEST_F(AudioRendererImplTest, Underflow_CapacityResetsAfterFlush) {
- Initialize();
- Preroll();
- StartTicking();
-
- // Drain internal buffer, we should have a pending read.
- EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
- WaitForPendingRead();
-
- // Verify the next FillBuffer() call triggers the underflow callback
- // since the decoder hasn't delivered any data after it was drained.
- OutputFrames initial_capacity = buffer_capacity();
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
- EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1)));
-
- // Verify that the buffer capacity increased as a result of underflowing.
- EXPECT_GT(buffer_capacity().value, initial_capacity.value);
-
- // Verify that the buffer capacity is restored to the |initial_capacity|.
- FlushDuringPendingRead();
- EXPECT_EQ(buffer_capacity().value, initial_capacity.value);
-}
-
-TEST_F(AudioRendererImplTest, Underflow_Flush) {
- Initialize();
- Preroll();
- StartTicking();
-
- // Force underflow.
- EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
- WaitForPendingRead();
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
- EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1)));
- WaitForPendingRead();
- StopTicking();
-
- // We shouldn't expect another buffering state change when flushing.
- FlushDuringPendingRead();
-}
-
-TEST_F(AudioRendererImplTest, PendingRead_Flush) {
- Initialize();
-
- Preroll();
- StartTicking();
-
- // Partially drain internal buffer so we get a pending read.
- EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256)));
- WaitForPendingRead();
-
- StopTicking();
-
- EXPECT_TRUE(IsReadPending());
-
- // Flush and expect to be notified that we have nothing.
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
- FlushDuringPendingRead();
-
- // Preroll again to a different timestamp and verify it completed normally.
- const base::TimeDelta seek_timestamp =
- base::TimeDelta::FromMilliseconds(1000);
- Preroll(seek_timestamp, seek_timestamp, PIPELINE_OK);
-}
-
-TEST_F(AudioRendererImplTest, PendingRead_Destroy) {
- Initialize();
-
- Preroll();
- StartTicking();
-
- // Partially drain internal buffer so we get a pending read.
- EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256)));
- WaitForPendingRead();
-
- StopTicking();
-
- EXPECT_TRUE(IsReadPending());
-
- renderer_.reset();
-}
-
-TEST_F(AudioRendererImplTest, PendingFlush_Destroy) {
- Initialize();
-
- Preroll();
- StartTicking();
-
- // Partially drain internal buffer so we get a pending read.
- EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256)));
- WaitForPendingRead();
-
- StopTicking();
-
- EXPECT_TRUE(IsReadPending());
-
- // Start flushing.
- WaitableMessageLoopEvent flush_event;
- renderer_->Flush(flush_event.GetClosure());
-
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
- SatisfyPendingRead(InputFrames(256));
-
- renderer_.reset();
-}
-
-TEST_F(AudioRendererImplTest, InitializeThenDestroy) {
- InitializeAndDestroy();
-}
-
-TEST_F(AudioRendererImplTest, InitializeThenDestroyDuringDecoderInit) {
- InitializeAndDestroyDuringDecoderInit();
-}
-
-TEST_F(AudioRendererImplTest, ConfigChangeDrainsConverter) {
- Initialize();
- Preroll();
- StartTicking();
-
- // Drain internal buffer, we should have a pending read.
- EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
- WaitForPendingRead();
-
- // Deliver a little bit of data. Use an odd data size to ensure there is data
- // left in the AudioBufferConverter. Ensure no buffers are in the splicer.
- SatisfyPendingRead(InputFrames(2053));
- EXPECT_FALSE(splicer_has_next_buffer());
- EXPECT_GT(converter_input_frames_left().value, 0);
-
- // Force a config change and then ensure all buffered data has been put into
- // the splicer.
- force_config_change();
- EXPECT_TRUE(splicer_has_next_buffer());
- EXPECT_EQ(0, converter_input_frames_left().value);
-}
-
-TEST_F(AudioRendererImplTest, TimeUpdatesOnFirstBuffer) {
- Initialize();
- Preroll();
- StartTicking();
-
- AudioTimestampHelper timestamp_helper(kOutputSamplesPerSecond);
- timestamp_helper.SetBaseTimestamp(base::TimeDelta());
-
- // Time should be the starting timestamp as nothing's been consumed yet.
- EXPECT_EQ(timestamp_helper.GetTimestamp(), CurrentMediaTime());
-
- // Consume some audio data.
- OutputFrames frames_to_consume(frames_buffered().value / 2);
- EXPECT_TRUE(ConsumeBufferedData(frames_to_consume));
- WaitForPendingRead();
-
- // Time shouldn't change just yet because we've only sent the initial audio
- // data to the hardware.
- EXPECT_EQ(timestamp_helper.GetTimestamp(), CurrentMediaTime());
-
- // Consume some more audio data.
- frames_to_consume = frames_buffered();
- EXPECT_TRUE(ConsumeBufferedData(frames_to_consume));
-
- // Now time should change now that the audio hardware has called back.
- timestamp_helper.AddFrames(frames_to_consume.value);
- EXPECT_EQ(timestamp_helper.GetTimestamp(), CurrentMediaTime());
-}
-
-TEST_F(AudioRendererImplTest, RenderingDelayedForEarlyStartTime) {
- Initialize();
-
- // Choose a first timestamp a few buffers into the future, which ends halfway
- // through the desired output buffer; this allows for maximum test coverage.
- const double kBuffers = 4.5;
- const base::TimeDelta first_timestamp = base::TimeDelta::FromSecondsD(
- hardware_config_.GetOutputBufferSize() * kBuffers /
- hardware_config_.GetOutputSampleRate());
-
- Preroll(base::TimeDelta(), first_timestamp, PIPELINE_OK);
- StartTicking();
-
- // Verify the first few buffers are silent.
- scoped_ptr<AudioBus> bus =
- AudioBus::Create(hardware_config_.GetOutputConfig());
- int frames_read = 0;
- for (int i = 0; i < std::floor(kBuffers); ++i) {
- EXPECT_TRUE(sink_->Render(bus.get(), 0, &frames_read));
- EXPECT_EQ(frames_read, bus->frames());
- for (int j = 0; j < bus->frames(); ++j)
- ASSERT_FLOAT_EQ(0.0f, bus->channel(0)[j]);
- WaitForPendingRead();
- DeliverRemainingAudio();
- }
-
- // Verify the last buffer is half silence and half real data.
- EXPECT_TRUE(sink_->Render(bus.get(), 0, &frames_read));
- EXPECT_EQ(frames_read, bus->frames());
- const int zero_frames =
- bus->frames() * (kBuffers - static_cast<int>(kBuffers));
-
- for (int i = 0; i < zero_frames; ++i)
- ASSERT_FLOAT_EQ(0.0f, bus->channel(0)[i]);
- for (int i = zero_frames; i < bus->frames(); ++i)
- ASSERT_NE(0.0f, bus->channel(0)[i]);
-}
-
-TEST_F(AudioRendererImplTest, ImmediateEndOfStream) {
- Initialize();
- {
- SCOPED_TRACE("Preroll()");
- renderer_->StartPlaying();
- WaitForPendingRead();
- EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
- DeliverEndOfStream();
- }
- StartTicking();
-
- // Read a single frame. We shouldn't be able to satisfy it.
- EXPECT_FALSE(ended());
- EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1)));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(ended());
-}
-
-TEST_F(AudioRendererImplTest, OnRenderErrorCausesDecodeError) {
- Initialize();
- Preroll();
- StartTicking();
-
- EXPECT_CALL(*this, OnError(PIPELINE_ERROR_DECODE));
- sink_->OnRenderError();
- base::RunLoop().RunUntilIdle();
-}
-
-// Test for AudioRendererImpl calling Pause()/Play() on the sink when the
-// playback rate is set to zero and non-zero.
-TEST_F(AudioRendererImplTest, SetPlaybackRate) {
- Initialize();
- Preroll();
-
- // Rendering hasn't started. Sink should always be paused.
- EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
- renderer_->SetPlaybackRate(0.0f);
- EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
- renderer_->SetPlaybackRate(1.0f);
- EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
-
- // Rendering has started with non-zero rate. Rate changes will affect sink
- // state.
- renderer_->StartTicking();
- EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state());
- renderer_->SetPlaybackRate(0.0f);
- EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
- renderer_->SetPlaybackRate(1.0f);
- EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state());
-
- // Rendering has stopped. Sink should be paused.
- renderer_->StopTicking();
- EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
-
- // Start rendering with zero playback rate. Sink should be paused until
- // non-zero rate is set.
- renderer_->SetPlaybackRate(0.0f);
- renderer_->StartTicking();
- EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
- renderer_->SetPlaybackRate(1.0f);
- EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state());
-}
-
-} // namespace media
« no previous file with comments | « media/filters/audio_renderer_impl.cc ('k') | media/filters/default_renderer_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698