| 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
|
| index 1504c71609d2cabaa951203c78b05d588e360e73..c8e47c5b0284324894c56f606161963732f07711 100644
|
| --- a/media/filters/audio_renderer_impl_unittest.cc
|
| +++ b/media/filters/audio_renderer_impl_unittest.cc
|
| @@ -6,6 +6,7 @@
|
| #include "base/callback_helpers.h"
|
| #include "base/run_loop.h"
|
| #include "base/strings/stringprintf.h"
|
| +#include "base/test/simple_test_tick_clock.h"
|
| #include "media/base/audio_buffer_converter.h"
|
| #include "media/base/audio_hardware_config.h"
|
| #include "media/base/audio_splicer.h"
|
| @@ -59,6 +60,7 @@ class AudioRendererImplTest : public ::testing::Test {
|
| // Give the decoder some non-garbage media properties.
|
| AudioRendererImplTest()
|
| : hardware_config_(AudioParameters(), AudioParameters()),
|
| + tick_clock_(new base::SimpleTestTickClock()),
|
| needs_stop_(true),
|
| demuxer_stream_(DemuxerStream::AUDIO),
|
| decoder_(new MockAudioDecoder()),
|
| @@ -99,6 +101,7 @@ class AudioRendererImplTest : public ::testing::Test {
|
| decoders.Pass(),
|
| SetDecryptorReadyCB(),
|
| &hardware_config_));
|
| + renderer_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
|
| }
|
|
|
| virtual ~AudioRendererImplTest() {
|
| @@ -227,13 +230,15 @@ class AudioRendererImplTest : public ::testing::Test {
|
| DeliverRemainingAudio();
|
| }
|
|
|
| - void StartRendering() {
|
| - renderer_->StartRendering();
|
| + void StartTicking() {
|
| + renderer_->StartTicking();
|
| renderer_->SetPlaybackRate(1.0f);
|
| }
|
|
|
| - void StopRendering() {
|
| - renderer_->StopRendering();
|
| + void StopTicking() { renderer_->StopTicking(); }
|
| +
|
| + int CurrentMediaTimeInMilliseconds() {
|
| + return renderer_->CurrentMediaTime().InMilliseconds();
|
| }
|
|
|
| bool IsReadPending() const {
|
| @@ -308,10 +313,15 @@ class AudioRendererImplTest : public ::testing::Test {
|
| // buffer. Returns true if and only if all of |requested_frames| were able
|
| // to be consumed.
|
| bool ConsumeBufferedData(OutputFrames requested_frames) {
|
| + return ConsumeBufferedDataWithDelay(requested_frames, 0);
|
| + }
|
| +
|
| + bool ConsumeBufferedDataWithDelay(OutputFrames requested_frames,
|
| + int delay_ms) {
|
| scoped_ptr<AudioBus> bus =
|
| AudioBus::Create(kChannels, requested_frames.value);
|
| int frames_read = 0;
|
| - EXPECT_TRUE(sink_->Render(bus.get(), 0, &frames_read));
|
| + EXPECT_TRUE(sink_->Render(bus.get(), delay_ms, &frames_read));
|
| return frames_read == requested_frames.value;
|
| }
|
|
|
| @@ -356,6 +366,7 @@ class AudioRendererImplTest : public ::testing::Test {
|
| scoped_ptr<AudioRendererImpl> renderer_;
|
| scoped_refptr<FakeAudioRendererSink> sink_;
|
| AudioHardwareConfig hardware_config_;
|
| + base::SimpleTestTickClock* tick_clock_; // Owned by |renderer_|.
|
|
|
| // Whether or not the test needs the destructor to call Stop() on
|
| // |renderer_| at destruction.
|
| @@ -446,10 +457,10 @@ TEST_F(AudioRendererImplTest, Preroll) {
|
| Preroll();
|
| }
|
|
|
| -TEST_F(AudioRendererImplTest, StartRendering) {
|
| +TEST_F(AudioRendererImplTest, StartTicking) {
|
| Initialize();
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Drain internal buffer, we should have a pending read.
|
| EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
|
| @@ -459,7 +470,7 @@ TEST_F(AudioRendererImplTest, StartRendering) {
|
| TEST_F(AudioRendererImplTest, EndOfStream) {
|
| Initialize();
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Drain internal buffer, we should have a pending read.
|
| EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
|
| @@ -486,7 +497,7 @@ TEST_F(AudioRendererImplTest, EndOfStream) {
|
| TEST_F(AudioRendererImplTest, Underflow) {
|
| Initialize();
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Drain internal buffer, we should have a pending read.
|
| EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
|
| @@ -512,7 +523,7 @@ TEST_F(AudioRendererImplTest, Underflow) {
|
| TEST_F(AudioRendererImplTest, Underflow_CapacityResetsAfterFlush) {
|
| Initialize();
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Drain internal buffer, we should have a pending read.
|
| EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
|
| @@ -535,7 +546,7 @@ TEST_F(AudioRendererImplTest, Underflow_CapacityResetsAfterFlush) {
|
| TEST_F(AudioRendererImplTest, Underflow_Flush) {
|
| Initialize();
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Force underflow.
|
| EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
|
| @@ -543,7 +554,7 @@ TEST_F(AudioRendererImplTest, Underflow_Flush) {
|
| EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_NOTHING));
|
| EXPECT_FALSE(ConsumeBufferedData(OutputFrames(1)));
|
| WaitForPendingRead();
|
| - StopRendering();
|
| + StopTicking();
|
|
|
| // We shouldn't expect another buffering state change when flushing.
|
| FlushDuringPendingRead();
|
| @@ -553,13 +564,13 @@ TEST_F(AudioRendererImplTest, PendingRead_Flush) {
|
| Initialize();
|
|
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Partially drain internal buffer so we get a pending read.
|
| EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256)));
|
| WaitForPendingRead();
|
|
|
| - StopRendering();
|
| + StopTicking();
|
|
|
| EXPECT_TRUE(IsReadPending());
|
|
|
| @@ -575,13 +586,13 @@ TEST_F(AudioRendererImplTest, PendingRead_Stop) {
|
| Initialize();
|
|
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Partially drain internal buffer so we get a pending read.
|
| EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256)));
|
| WaitForPendingRead();
|
|
|
| - StopRendering();
|
| + StopTicking();
|
|
|
| EXPECT_TRUE(IsReadPending());
|
|
|
| @@ -600,13 +611,13 @@ TEST_F(AudioRendererImplTest, PendingFlush_Stop) {
|
| Initialize();
|
|
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Partially drain internal buffer so we get a pending read.
|
| EXPECT_TRUE(ConsumeBufferedData(OutputFrames(256)));
|
| WaitForPendingRead();
|
|
|
| - StopRendering();
|
| + StopTicking();
|
|
|
| EXPECT_TRUE(IsReadPending());
|
|
|
| @@ -634,7 +645,7 @@ TEST_F(AudioRendererImplTest, InitializeThenStopDuringDecoderInit) {
|
| TEST_F(AudioRendererImplTest, ConfigChangeDrainsConverter) {
|
| Initialize();
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Drain internal buffer, we should have a pending read.
|
| EXPECT_TRUE(ConsumeBufferedData(frames_buffered()));
|
| @@ -656,7 +667,7 @@ TEST_F(AudioRendererImplTest, ConfigChangeDrainsConverter) {
|
| TEST_F(AudioRendererImplTest, TimeUpdatesOnFirstBuffer) {
|
| Initialize();
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| AudioTimestampHelper timestamp_helper(kOutputSamplesPerSecond);
|
| EXPECT_EQ(kNoTimestamp(), last_time_update());
|
| @@ -693,7 +704,7 @@ TEST_F(AudioRendererImplTest, ImmediateEndOfStream) {
|
| EXPECT_CALL(*this, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH));
|
| DeliverEndOfStream();
|
| }
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| // Read a single frame. We shouldn't be able to satisfy it.
|
| EXPECT_FALSE(ended());
|
| @@ -704,7 +715,7 @@ TEST_F(AudioRendererImplTest, ImmediateEndOfStream) {
|
| TEST_F(AudioRendererImplTest, OnRenderErrorCausesDecodeError) {
|
| Initialize();
|
| Preroll();
|
| - StartRendering();
|
| + StartTicking();
|
|
|
| EXPECT_CALL(*this, OnError(PIPELINE_ERROR_DECODE));
|
| sink_->OnRenderError();
|
| @@ -725,7 +736,7 @@ TEST_F(AudioRendererImplTest, SetPlaybackRate) {
|
|
|
| // Rendering has started with non-zero rate. Rate changes will affect sink
|
| // state.
|
| - renderer_->StartRendering();
|
| + renderer_->StartTicking();
|
| EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state());
|
| renderer_->SetPlaybackRate(0.0f);
|
| EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
|
| @@ -733,16 +744,83 @@ TEST_F(AudioRendererImplTest, SetPlaybackRate) {
|
| EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state());
|
|
|
| // Rendering has stopped. Sink should be paused.
|
| - renderer_->StopRendering();
|
| + 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_->StartRendering();
|
| + renderer_->StartTicking();
|
| EXPECT_EQ(FakeAudioRendererSink::kPaused, sink_->state());
|
| renderer_->SetPlaybackRate(1.0f);
|
| EXPECT_EQ(FakeAudioRendererSink::kPlaying, sink_->state());
|
| }
|
|
|
| +TEST_F(AudioRendererImplTest, CurrentMediaTime) {
|
| + // Time should start off as zero after initializing.
|
| + Initialize();
|
| + EXPECT_EQ(0, CurrentMediaTimeInMilliseconds());
|
| +
|
| + // Time should match set media time after prerolling.
|
| + Preroll(1000, PIPELINE_OK);
|
| + EXPECT_EQ(1000, CurrentMediaTimeInMilliseconds());
|
| +
|
| + renderer_->SetPlaybackRate(1.0f);
|
| + renderer_->StartTicking();
|
| + EXPECT_EQ(1000, CurrentMediaTimeInMilliseconds());
|
| +
|
| + // To keep the tests simple, we'll have a hardware delay that's 400ms long
|
| + // and consume 100ms at a time.
|
| + //
|
| + // That means we'll need to consume data 4 times before we should start
|
| + // seeing media time advancing.
|
| + const InputFrames kSatisfyFrames(kInputSamplesPerSecond / 10);
|
| + const OutputFrames kConsumeFrames(kOutputSamplesPerSecond / 10);
|
| + const int kConsumeFramesMs = 100;
|
| + const int kDelayMs = 400;
|
| +
|
| + // Read 1/4: Time shouldn't advance as there's still hardware delay.
|
| + ConsumeBufferedDataWithDelay(kConsumeFrames, kDelayMs);
|
| + SatisfyPendingRead(kSatisfyFrames);
|
| + EXPECT_EQ(1000, CurrentMediaTimeInMilliseconds());
|
| +
|
| + // Read 2/4: Time shouldn't advance as there's still hardware delay.
|
| + ConsumeBufferedDataWithDelay(kConsumeFrames, kDelayMs);
|
| + SatisfyPendingRead(kSatisfyFrames);
|
| + EXPECT_EQ(1000, CurrentMediaTimeInMilliseconds());
|
| +
|
| + // Read 3/4: Time shouldn't advance as there's still hardware delay.
|
| + ConsumeBufferedDataWithDelay(kConsumeFrames, kDelayMs);
|
| + SatisfyPendingRead(kSatisfyFrames);
|
| + EXPECT_EQ(1000, CurrentMediaTimeInMilliseconds());
|
| +
|
| + // Read 4/4: Time shouldn't advance as there's still hardware delay.
|
| + ConsumeBufferedDataWithDelay(kConsumeFrames, kDelayMs);
|
| + SatisfyPendingRead(kSatisfyFrames);
|
| + EXPECT_EQ(1000, CurrentMediaTimeInMilliseconds());
|
| +
|
| + // At this point time *should* start advancing.
|
| + ConsumeBufferedDataWithDelay(kConsumeFrames, kDelayMs);
|
| + SatisfyPendingRead(kSatisfyFrames);
|
| + EXPECT_EQ(1000 + kConsumeFramesMs, CurrentMediaTimeInMilliseconds());
|
| +
|
| + ConsumeBufferedDataWithDelay(kConsumeFrames, kDelayMs);
|
| + SatisfyPendingRead(kSatisfyFrames);
|
| + EXPECT_EQ(1000 + kConsumeFramesMs * 2, CurrentMediaTimeInMilliseconds());
|
| +
|
| + // Test advancing the system clock to ensure we get approximated time.
|
| + tick_clock_->Advance(base::TimeDelta::FromMilliseconds(100));
|
| + EXPECT_EQ(1000 + kConsumeFramesMs * 2 + 100,
|
| + CurrentMediaTimeInMilliseconds());
|
| +
|
| + tick_clock_->Advance(base::TimeDelta::FromMilliseconds(100));
|
| + EXPECT_EQ(1000 + kConsumeFramesMs * 2 + 200,
|
| + CurrentMediaTimeInMilliseconds());
|
| +
|
| + // Test consume more data, which should reset the approximated time.
|
| + ConsumeBufferedDataWithDelay(kConsumeFrames, kDelayMs);
|
| + SatisfyPendingRead(kSatisfyFrames);
|
| + EXPECT_EQ(1000 + kConsumeFramesMs * 3, CurrentMediaTimeInMilliseconds());
|
| +}
|
| +
|
| } // namespace media
|
|
|