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 |