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

Unified Diff: media/mojo/services/mojo_renderer_service.cc

Issue 680533004: Modify MojoRendererService to host a RendererImpl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments. Created 6 years, 2 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/mojo/services/mojo_renderer_service.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/mojo/services/mojo_renderer_service.cc
diff --git a/media/mojo/services/mojo_renderer_service.cc b/media/mojo/services/mojo_renderer_service.cc
index e9eee8e446a4a3319a943615da8e43dc32abf780..4987751b3b4e63bbb1da6ba1ca7d37bbcacb346c 100644
--- a/media/mojo/services/mojo_renderer_service.cc
+++ b/media/mojo/services/mojo_renderer_service.cc
@@ -12,7 +12,9 @@
#include "media/base/audio_renderer_sink.h"
#include "media/base/decryptor.h"
#include "media/base/media_log.h"
+#include "media/base/video_renderer.h"
#include "media/filters/audio_renderer_impl.h"
+#include "media/filters/renderer_impl.h"
#include "media/mojo/services/mojo_demuxer_stream_adapter.h"
#include "media/mojo/services/renderer_config.h"
#include "mojo/application/application_runner_chromium.h"
@@ -31,9 +33,29 @@ static void LogMediaSourceError(const scoped_refptr<MediaLog>& media_log,
media_log->AddEvent(media_log->CreateMediaSourceErrorEvent(error));
}
-static base::TimeDelta TimeUpdateInterval() {
- return base::TimeDelta::FromMilliseconds(kTimeUpdateIntervalMs);
-}
+// Shim DemuxerStreamProvider wrapper for a single DemuxerStream.
+// TODO(dalecurtis): Once we support more than one DemuxerStream we'll need a
+// more complicated shim which can handle a mojo::Array<DemuxerStream>.
+class DemuxerStreamProviderShim : public DemuxerStreamProvider {
+ public:
+ DemuxerStreamProviderShim(scoped_ptr<MojoDemuxerStreamAdapter> stream)
+ : stream_(stream.Pass()) {}
+
+ ~DemuxerStreamProviderShim() override {}
+
+ DemuxerStream* GetStream(DemuxerStream::Type type) override {
+ return type != stream_->type() ? nullptr : stream_.get();
+ };
+
+ Liveness GetLiveness() const override {
+ return DemuxerStreamProvider::LIVENESS_UNKNOWN;
+ }
+
+ private:
+ scoped_ptr<MojoDemuxerStreamAdapter> stream_;
+
+ DISALLOW_COPY_AND_ASSIGN(DemuxerStreamProviderShim);
+};
class MojoRendererApplication
: public mojo::ApplicationDelegate,
@@ -53,225 +75,148 @@ class MojoRendererApplication
}
};
-// TODO(xhwang): This class looks insanely similar to RendererImpl. We should
-// really host a Renderer in this class instead of a AudioRenderer.
+static void MojoTrampoline(const mojo::Closure& closure) {
+ closure.Run();
+}
MojoRendererService::MojoRendererService(
mojo::ApplicationConnection* connection)
: state_(STATE_UNINITIALIZED),
- time_source_(NULL),
- time_ticking_(false),
- ended_(false),
+ last_media_time_usec_(0),
weak_factory_(this),
weak_this_(weak_factory_.GetWeakPtr()) {
DVLOG(1) << __FUNCTION__;
- scoped_refptr<base::SingleThreadTaskRunner> runner(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner(
base::MessageLoop::current()->task_runner());
scoped_refptr<MediaLog> media_log(new MediaLog());
RendererConfig* renderer_config = RendererConfig::Get();
audio_renderer_sink_ = renderer_config->GetAudioRendererSink();
- audio_renderer_.reset(new AudioRendererImpl(
- runner,
+ scoped_ptr<AudioRenderer> audio_renderer(new AudioRendererImpl(
+ task_runner,
audio_renderer_sink_.get(),
renderer_config->GetAudioDecoders(
- runner, base::Bind(&LogMediaSourceError, media_log))
- .Pass(),
+ task_runner,
+ base::Bind(&LogMediaSourceError, media_log)).Pass(),
SetDecryptorReadyCB(),
renderer_config->GetAudioHardwareConfig(),
media_log));
+ scoped_ptr<VideoRenderer> video_renderer(nullptr);
+
+ // Create renderer.
+ renderer_.reset(new RendererImpl(
+ task_runner, audio_renderer.Pass(), video_renderer.Pass()));
}
MojoRendererService::~MojoRendererService() {
}
void MojoRendererService::Initialize(mojo::DemuxerStreamPtr stream,
- const mojo::Callback<void()>& callback) {
+ const mojo::Closure& callback) {
DVLOG(1) << __FUNCTION__;
- DCHECK_EQ(state_, STATE_UNINITIALIZED) << state_;
+ DCHECK_EQ(state_, STATE_UNINITIALIZED);
DCHECK(client());
- init_cb_ = callback;
state_ = STATE_INITIALIZING;
- stream_.reset(new MojoDemuxerStreamAdapter(
- stream.Pass(),
- base::Bind(&MojoRendererService::OnStreamReady, weak_this_)));
+ stream_provider_.reset(new DemuxerStreamProviderShim(
+ make_scoped_ptr(new MojoDemuxerStreamAdapter(
+ stream.Pass(),
+ base::Bind(&MojoRendererService::OnStreamReady,
+ weak_this_,
+ callback))).Pass()));
}
-void MojoRendererService::Flush(const mojo::Callback<void()>& callback) {
+void MojoRendererService::Flush(const mojo::Closure& callback) {
DVLOG(2) << __FUNCTION__;
- DCHECK_EQ(state_, STATE_PLAYING) << state_;
+ DCHECK_EQ(state_, STATE_PLAYING);
state_ = STATE_FLUSHING;
- if (time_ticking_)
- PausePlayback();
-
- // TODO(xhwang): This is not completed. Finish the flushing path.
- NOTIMPLEMENTED();
+ time_update_timer_.Reset();
+ renderer_->Flush(base::Bind(&MojoTrampoline, callback));
}
void MojoRendererService::StartPlayingFrom(int64_t time_delta_usec) {
DVLOG(2) << __FUNCTION__ << ": " << time_delta_usec;
- base::TimeDelta time = base::TimeDelta::FromMicroseconds(time_delta_usec);
- time_source_->SetMediaTime(time);
- audio_renderer_->StartPlaying();
+ renderer_->StartPlayingFrom(
+ base::TimeDelta::FromMicroseconds(time_delta_usec));
+ SchedulePeriodicMediaTimeUpdates();
}
void MojoRendererService::SetPlaybackRate(float playback_rate) {
DVLOG(2) << __FUNCTION__ << ": " << playback_rate;
-
- // Playback rate changes are only carried out while playing.
- if (state_ != STATE_PLAYING)
- return;
-
- time_source_->SetPlaybackRate(playback_rate);
+ DCHECK_EQ(state_, STATE_PLAYING);
+ renderer_->SetPlaybackRate(playback_rate);
}
void MojoRendererService::SetVolume(float volume) {
- if (audio_renderer_)
- audio_renderer_->SetVolume(volume);
+ renderer_->SetVolume(volume);
}
-void MojoRendererService::OnStreamReady() {
- DCHECK_EQ(state_, STATE_INITIALIZING) << state_;
- audio_renderer_->Initialize(
- stream_.get(),
- base::Bind(&MojoRendererService::OnAudioRendererInitializeDone,
- weak_this_),
+void MojoRendererService::OnStreamReady(const mojo::Closure& callback) {
+ DCHECK_EQ(state_, STATE_INITIALIZING);
+
+ renderer_->Initialize(
+ stream_provider_.get(),
+ base::Bind(
+ &MojoRendererService::OnRendererInitializeDone, weak_this_, callback),
base::Bind(&MojoRendererService::OnUpdateStatistics, weak_this_),
- base::Bind(&MojoRendererService::OnBufferingStateChanged, weak_this_),
- base::Bind(&MojoRendererService::OnAudioRendererEnded, weak_this_),
- base::Bind(&MojoRendererService::OnError, weak_this_));
+ base::Bind(&MojoRendererService::OnRendererEnded, weak_this_),
+ base::Bind(&MojoRendererService::OnError, weak_this_),
+ base::Bind(&MojoRendererService::OnBufferingStateChanged, weak_this_));
}
-void MojoRendererService::OnAudioRendererInitializeDone(PipelineStatus status) {
- DVLOG(1) << __FUNCTION__ << ": " << status;
- DCHECK_EQ(state_, STATE_INITIALIZING) << state_;
+void MojoRendererService::OnRendererInitializeDone(
+ const mojo::Closure& callback) {
+ DVLOG(1) << __FUNCTION__;
- if (status != PIPELINE_OK) {
- state_ = STATE_ERROR;
- audio_renderer_.reset();
- client()->OnError();
- init_cb_.Run();
- init_cb_.reset();
- return;
+ if (state_ == STATE_ERROR) {
+ renderer_.reset();
+ } else {
+ DCHECK_EQ(state_, STATE_INITIALIZING);
+ state_ = STATE_PLAYING;
}
- time_source_ = audio_renderer_->GetTimeSource();
-
- state_ = STATE_PLAYING;
- init_cb_.Run();
- init_cb_.reset();
+ callback.Run();
}
void MojoRendererService::OnUpdateStatistics(const PipelineStatistics& stats) {
- NOTIMPLEMENTED();
}
-void MojoRendererService::UpdateMediaTime() {
- uint64_t media_time = time_source_->CurrentMediaTime().InMicroseconds();
+void MojoRendererService::UpdateMediaTime(bool force) {
+ const uint64_t media_time = renderer_->GetMediaTime().InMicroseconds();
+ if (!force && media_time == last_media_time_usec_)
+ return;
+
client()->OnTimeUpdate(media_time, media_time);
+ last_media_time_usec_ = media_time;
}
void MojoRendererService::SchedulePeriodicMediaTimeUpdates() {
- // Update media time immediately.
- UpdateMediaTime();
-
- // Then setup periodic time update.
+ UpdateMediaTime(true);
time_update_timer_.Start(
FROM_HERE,
- TimeUpdateInterval(),
- base::Bind(&MojoRendererService::UpdateMediaTime, weak_this_));
+ base::TimeDelta::FromMilliseconds(kTimeUpdateIntervalMs),
+ base::Bind(&MojoRendererService::UpdateMediaTime, weak_this_, false));
}
void MojoRendererService::OnBufferingStateChanged(
- media::BufferingState new_buffering_state) {
- DVLOG(2) << __FUNCTION__ << "(" << buffering_state_ << ", "
- << new_buffering_state << ") ";
- bool was_waiting_for_enough_data = WaitingForEnoughData();
-
- buffering_state_ = new_buffering_state;
-
- // Renderer underflowed.
- if (!was_waiting_for_enough_data && WaitingForEnoughData()) {
- PausePlayback();
- // TODO(xhwang): Notify client of underflow condition.
- return;
- }
-
- // Renderer prerolled.
- if (was_waiting_for_enough_data && !WaitingForEnoughData()) {
- StartPlayback();
- client()->OnBufferingStateChange(
- static_cast<mojo::BufferingState>(new_buffering_state));
- return;
- }
+ BufferingState new_buffering_state) {
+ DVLOG(2) << __FUNCTION__ << "(" << new_buffering_state << ") ";
+ client()->OnBufferingStateChange(
+ static_cast<mojo::BufferingState>(new_buffering_state));
}
-void MojoRendererService::OnAudioRendererEnded() {
+void MojoRendererService::OnRendererEnded() {
DVLOG(1) << __FUNCTION__;
-
- if (state_ != STATE_PLAYING)
- return;
-
- DCHECK(!ended_);
- ended_ = true;
-
- if (time_ticking_)
- PausePlayback();
-
client()->OnEnded();
+ time_update_timer_.Reset();
}
void MojoRendererService::OnError(PipelineStatus error) {
- client()->OnError();
-}
-
-bool MojoRendererService::WaitingForEnoughData() const {
- DCHECK(audio_renderer_);
-
- return state_ == STATE_PLAYING && buffering_state_ != BUFFERING_HAVE_ENOUGH;
-}
-
-void MojoRendererService::StartPlayback() {
DVLOG(1) << __FUNCTION__;
- DCHECK_EQ(state_, STATE_PLAYING);
- DCHECK(!time_ticking_);
- DCHECK(!WaitingForEnoughData());
-
- time_ticking_ = true;
- time_source_->StartTicking();
-
- SchedulePeriodicMediaTimeUpdates();
-}
-
-void MojoRendererService::PausePlayback() {
- DVLOG(1) << __FUNCTION__;
- DCHECK(time_ticking_);
- switch (state_) {
- case STATE_PLAYING:
- DCHECK(ended_ || WaitingForEnoughData())
- << "Playback should only pause due to ending or underflowing";
- break;
-
- case STATE_FLUSHING:
- // It's OK to pause playback when flushing.
- break;
-
- case STATE_UNINITIALIZED:
- case STATE_INITIALIZING:
- case STATE_ERROR:
- NOTREACHED() << "Invalid state: " << state_;
- break;
- }
-
- time_ticking_ = false;
- time_source_->StopTicking();
-
- // Cancel repeating time update timer and update the current media time.
- time_update_timer_.Stop();
- UpdateMediaTime();
+ state_ = STATE_ERROR;
+ client()->OnError();
}
} // namespace media
« no previous file with comments | « media/mojo/services/mojo_renderer_service.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698