Commit 5cc4fb59 authored by dalecurtis's avatar dalecurtis Committed by Commit bot

Introduce TimeSource notifications to the VideoRenderer.

The upcoming VideoRenderer needs a way to know when time starts and
stops moving; this extends the RendererImpl to let the VideoRenderer
know about time changes.

I considered introducing a TimeSourceDependent observer-like interface
for TimeSources, but it ended up being way more complicated. I also
considered a proxy TimeSource, but again it was way more complicated.
The approach here is quite simple and small in complexity.

BUG=439548
TEST=new unittest.

Review URL: https://codereview.chromium.org/1068593003

Cr-Commit-Position: refs/heads/master@{#324172}
parent fb9d8f3c
......@@ -134,6 +134,7 @@ class MockVideoRenderer : public VideoRenderer {
const base::Closure& waiting_for_decryption_key_cb));
MOCK_METHOD1(Flush, void(const base::Closure& callback));
MOCK_METHOD1(StartPlayingFrom, void(base::TimeDelta));
MOCK_METHOD1(OnTimeStateChanged, void(bool));
private:
DISALLOW_COPY_AND_ASSIGN(MockVideoRenderer);
......
......@@ -82,6 +82,11 @@ class MEDIA_EXPORT VideoRenderer {
// Only valid to call after a successful Initialize() or Flush().
virtual void StartPlayingFrom(base::TimeDelta timestamp) = 0;
// Called when time starts or stops moving. Time progresses when a base time
// has been set and the playback rate is > 0. If either condition changes,
// |time_progressing| will be false.
virtual void OnTimeStateChanged(bool time_progressing) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(VideoRenderer);
};
......
......@@ -35,6 +35,7 @@ RendererImpl::RendererImpl(
video_renderer_(video_renderer.Pass()),
time_source_(NULL),
time_ticking_(false),
playback_rate_(0),
audio_buffering_state_(BUFFERING_HAVE_NOTHING),
video_buffering_state_(BUFFERING_HAVE_NOTHING),
audio_ended_(false),
......@@ -177,6 +178,16 @@ void RendererImpl::SetPlaybackRate(float playback_rate) {
return;
time_source_->SetPlaybackRate(playback_rate);
const float old_rate = playback_rate_;
playback_rate_ = playback_rate;
if (!time_ticking_ || !video_renderer_)
return;
if (old_rate == 0 && playback_rate > 0)
video_renderer_->OnTimeStateChanged(true);
else if (old_rate > 0 && playback_rate == 0)
video_renderer_->OnTimeStateChanged(false);
}
void RendererImpl::SetVolume(float volume) {
......@@ -532,6 +543,8 @@ void RendererImpl::PausePlayback() {
time_ticking_ = false;
time_source_->StopTicking();
if (playback_rate_ > 0 && video_renderer_)
video_renderer_->OnTimeStateChanged(false);
}
void RendererImpl::StartPlayback() {
......@@ -543,6 +556,8 @@ void RendererImpl::StartPlayback() {
time_ticking_ = true;
time_source_->StartTicking();
if (playback_rate_ > 0 && video_renderer_)
video_renderer_->OnTimeStateChanged(true);
}
void RendererImpl::OnAudioRendererEnded() {
......
......@@ -154,6 +154,7 @@ class MEDIA_EXPORT RendererImpl : public Renderer {
TimeSource* time_source_;
scoped_ptr<WallClockTimeSource> wall_clock_time_source_;
bool time_ticking_;
float playback_rate_;
// The time to start playback from after starting/seeking has completed.
base::TimeDelta start_time_;
......
......@@ -320,6 +320,41 @@ TEST_F(RendererImplTest, StartPlayingFrom) {
Play();
}
TEST_F(RendererImplTest, StartPlayingFromWithPlaybackRate) {
InitializeWithAudioAndVideo();
// Play with a zero playback rate shouldn't start time.
Play();
Mock::VerifyAndClearExpectations(video_renderer_);
// Positive playback rate when ticking should start time.
EXPECT_CALL(*video_renderer_, OnTimeStateChanged(true));
SetPlaybackRate(1.0);
Mock::VerifyAndClearExpectations(video_renderer_);
// Double notifications shouldn't be sent.
SetPlaybackRate(1.0);
Mock::VerifyAndClearExpectations(video_renderer_);
// Zero playback rate should stop time.
EXPECT_CALL(*video_renderer_, OnTimeStateChanged(false));
SetPlaybackRate(0.0);
Mock::VerifyAndClearExpectations(video_renderer_);
// Double notifications shouldn't be sent.
SetPlaybackRate(0.0);
Mock::VerifyAndClearExpectations(video_renderer_);
// Starting playback and flushing should cause time to stop.
EXPECT_CALL(*video_renderer_, OnTimeStateChanged(true));
EXPECT_CALL(*video_renderer_, OnTimeStateChanged(false));
SetPlaybackRate(1.0);
Flush(false);
// A positive playback rate when playback isn't started should do nothing.
SetPlaybackRate(1.0);
}
TEST_F(RendererImplTest, FlushAfterInitialization) {
InitializeWithAudioAndVideo();
Flush(true);
......
......@@ -275,6 +275,10 @@ void VideoRendererImpl::SetTickClockForTesting(
tick_clock_.swap(tick_clock);
}
void VideoRendererImpl::OnTimeStateChanged(bool time_progressing) {
// TODO(dalecurtis): Wire up to the VideoRendererSink once it's implemented.
}
void VideoRendererImpl::PaintNextReadyFrame_Locked() {
lock_.AssertAcquired();
......
......@@ -65,6 +65,7 @@ class MEDIA_EXPORT VideoRendererImpl
const base::Closure& waiting_for_decryption_key_cb) override;
void Flush(const base::Closure& callback) override;
void StartPlayingFrom(base::TimeDelta timestamp) override;
void OnTimeStateChanged(bool time_progressing) override;
// PlatformThread::Delegate implementation.
void ThreadMain() override;
......
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