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

Unified Diff: chromecast/renderer/media/media_pipeline_proxy.cc

Issue 814403002: [Chromecast] Add CmaMediaRendererFactory and IPC proxy components (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years 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 | « chromecast/renderer/media/media_pipeline_proxy.h ('k') | chromecast/renderer/media/video_pipeline_proxy.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chromecast/renderer/media/media_pipeline_proxy.cc
diff --git a/chromecast/renderer/media/media_pipeline_proxy.cc b/chromecast/renderer/media/media_pipeline_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7a454b166664e124028d8ad3c26f25e1525a9ccd
--- /dev/null
+++ b/chromecast/renderer/media/media_pipeline_proxy.cc
@@ -0,0 +1,283 @@
+// Copyright 2014 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 "chromecast/renderer/media/media_pipeline_proxy.h"
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "chromecast/common/media/cma_messages.h"
+#include "chromecast/media/cma/base/coded_frame_provider.h"
+#include "chromecast/renderer/media/audio_pipeline_proxy.h"
+#include "chromecast/renderer/media/media_channel_proxy.h"
+#include "chromecast/renderer/media/video_pipeline_proxy.h"
+
+namespace chromecast {
+namespace media {
+
+// MediaPipelineProxyInternal -
+// This class is not thread safe and should run on the same thread
+// as the media channel proxy.
+class MediaPipelineProxyInternal {
+ public:
+ static void Release(scoped_ptr<MediaPipelineProxyInternal> proxy);
+
+ explicit MediaPipelineProxyInternal(
+ scoped_refptr<MediaChannelProxy> media_channel_proxy);
+ virtual ~MediaPipelineProxyInternal();
+
+ void SetClient(const MediaPipelineClient& client);
+ void SetCdm(int render_frame_id, int cdm_id);
+ void StartPlayingFrom(const base::TimeDelta& time);
+ void Flush(const ::media::PipelineStatusCB& status_cb);
+ void Stop();
+ void SetPlaybackRate(float playback_rate);
+
+ private:
+ void Shutdown();
+
+ // Callbacks for CmaMessageFilterHost::MediaDelegate.
+ void OnStateChanged(::media::PipelineStatus status);
+
+ base::ThreadChecker thread_checker_;
+
+ scoped_refptr<MediaChannelProxy> media_channel_proxy_;
+
+ MediaPipelineClient client_;
+
+ // Store the callback for a pending state transition.
+ ::media::PipelineStatusCB status_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaPipelineProxyInternal);
+};
+
+// static
+void MediaPipelineProxyInternal::Release(
+ scoped_ptr<MediaPipelineProxyInternal> proxy) {
+ proxy->Shutdown();
+}
+
+MediaPipelineProxyInternal::MediaPipelineProxyInternal(
+ scoped_refptr<MediaChannelProxy> media_channel_proxy)
+ : media_channel_proxy_(media_channel_proxy) {
+ DCHECK(media_channel_proxy.get());
+
+ // Creation can be done on a different thread.
+ thread_checker_.DetachFromThread();
+}
+
+MediaPipelineProxyInternal::~MediaPipelineProxyInternal() {
+}
+
+void MediaPipelineProxyInternal::Shutdown() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Remove any callback on VideoPipelineProxyInternal.
+ media_channel_proxy_->SetMediaDelegate(
+ CmaMessageFilterProxy::MediaDelegate());
+}
+
+void MediaPipelineProxyInternal::SetClient(
+ const MediaPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!client.error_cb.is_null());
+ DCHECK(!client.buffering_state_cb.is_null());
+ client_ = client;
+
+ CmaMessageFilterProxy::MediaDelegate delegate;
+ delegate.state_changed_cb =
+ base::Bind(&MediaPipelineProxyInternal::OnStateChanged,
+ base::Unretained(this));
+ delegate.client = client;
+ bool success = media_channel_proxy_->SetMediaDelegate(delegate);
+ CHECK(success);
+}
+
+void MediaPipelineProxyInternal::SetCdm(int render_frame_id, int cdm_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_SetCdm(media_channel_proxy_->GetId(),
+ render_frame_id,
+ cdm_id)));
+ LOG_IF(ERROR, !success) << "Failed to send SetCdm=" << cdm_id;
+}
+
+void MediaPipelineProxyInternal::Flush(
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_Flush(media_channel_proxy_->GetId())));
+ if (!success) {
+ status_cb.Run(::media::PIPELINE_ERROR_ABORT);
+ return;
+ }
+ DCHECK(status_cb_.is_null());
+ status_cb_ = status_cb;
+}
+
+void MediaPipelineProxyInternal::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_Stop(media_channel_proxy_->GetId())));
+ if (!success)
+ client_.error_cb.Run(::media::PIPELINE_ERROR_ABORT);
+}
+
+void MediaPipelineProxyInternal::StartPlayingFrom(const base::TimeDelta& time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ bool success = media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_StartPlayingFrom(
+ media_channel_proxy_->GetId(), time)));
+ if (!success)
+ client_.error_cb.Run(::media::PIPELINE_ERROR_ABORT);
+}
+
+void MediaPipelineProxyInternal::SetPlaybackRate(float playback_rate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ media_channel_proxy_->Send(scoped_ptr<IPC::Message>(
+ new CmaHostMsg_SetPlaybackRate(
+ media_channel_proxy_->GetId(), playback_rate)));
+}
+
+void MediaPipelineProxyInternal::OnStateChanged(
+ ::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(!status_cb_.is_null());
+ base::ResetAndReturn(&status_cb_).Run(status);
+}
+
+
+// A macro runs current member function on |io_message_loop_proxy_| thread.
+#define FORWARD_ON_IO_THREAD(param_fn, ...) \
+ io_message_loop_proxy_->PostTask( \
+ FROM_HERE, \
+ base::Bind(&MediaPipelineProxyInternal::param_fn, \
+ base::Unretained(proxy_.get()), ##__VA_ARGS__))
+
+MediaPipelineProxy::MediaPipelineProxy(
+ int render_frame_id,
+ scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy,
+ LoadType load_type)
+ : io_message_loop_proxy_(io_message_loop_proxy),
+ render_frame_id_(render_frame_id),
+ media_channel_proxy_(new MediaChannelProxy),
+ proxy_(new MediaPipelineProxyInternal(media_channel_proxy_)),
+ has_audio_(false),
+ has_video_(false),
+ audio_pipeline_(new AudioPipelineProxy(
+ io_message_loop_proxy, media_channel_proxy_)),
+ video_pipeline_(new VideoPipelineProxy(
+ io_message_loop_proxy, media_channel_proxy_)),
+ weak_factory_(this) {
+ weak_this_ = weak_factory_.GetWeakPtr();
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaChannelProxy::Open, media_channel_proxy_,
+ load_type));
+ thread_checker_.DetachFromThread();
+}
+
+MediaPipelineProxy::~MediaPipelineProxy() {
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaPipelineProxyInternal::Release, base::Passed(&proxy_)));
+ io_message_loop_proxy_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaChannelProxy::Close, media_channel_proxy_));
+}
+
+void MediaPipelineProxy::SetClient(
+ const MediaPipelineClient& client) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(SetClient, client);
+}
+
+void MediaPipelineProxy::SetCdm(int cdm_id) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(SetCdm, render_frame_id_, cdm_id);
+}
+
+AudioPipeline* MediaPipelineProxy::GetAudioPipeline() const {
+ return audio_pipeline_.get();
+}
+
+VideoPipeline* MediaPipelineProxy::GetVideoPipeline() const {
+ return video_pipeline_.get();
+}
+
+void MediaPipelineProxy::InitializeAudio(
+ const ::media::AudioDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ has_audio_ = true;
+ audio_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
+}
+
+void MediaPipelineProxy::InitializeVideo(
+ const ::media::VideoDecoderConfig& config,
+ scoped_ptr<CodedFrameProvider> frame_provider,
+ const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ has_video_ = true;
+ video_pipeline_->Initialize(config, frame_provider.Pass(), status_cb);
+}
+
+void MediaPipelineProxy::StartPlayingFrom(base::TimeDelta time) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (has_audio_)
+ audio_pipeline_->StartFeeding();
+ if (has_video_)
+ video_pipeline_->StartFeeding();
+ FORWARD_ON_IO_THREAD(StartPlayingFrom, time);
+}
+
+void MediaPipelineProxy::Flush(const ::media::PipelineStatusCB& status_cb) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(has_audio_ || has_video_);
+
+ ::media::SerialRunner::Queue bound_fns;
+ if (has_audio_) {
+ bound_fns.Push(base::Bind(&AudioPipelineProxy::Flush,
+ base::Unretained(audio_pipeline_.get())));
+ }
+ if (has_video_) {
+ bound_fns.Push(base::Bind(&VideoPipelineProxy::Flush,
+ base::Unretained(video_pipeline_.get())));
+ }
+ ::media::PipelineStatusCB cb =
+ base::Bind(&MediaPipelineProxy::OnProxyFlushDone, weak_this_, status_cb);
+ pending_callbacks_ = ::media::SerialRunner::Run(bound_fns, cb);
+}
+
+void MediaPipelineProxy::OnProxyFlushDone(
+ const ::media::PipelineStatusCB& status_cb,
+ ::media::PipelineStatus status) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(status, ::media::PIPELINE_OK);
+ pending_callbacks_.reset();
+ FORWARD_ON_IO_THREAD(Flush, status_cb);
+}
+
+void MediaPipelineProxy::Stop() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(has_audio_ || has_video_);
+
+ if (has_audio_)
+ audio_pipeline_->Stop();
+ if (has_video_)
+ video_pipeline_->Stop();
+
+ FORWARD_ON_IO_THREAD(Stop);
+}
+
+void MediaPipelineProxy::SetPlaybackRate(float playback_rate) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ FORWARD_ON_IO_THREAD(SetPlaybackRate, playback_rate);
+}
+
+} // namespace cma
+} // namespace chromecast
« no previous file with comments | « chromecast/renderer/media/media_pipeline_proxy.h ('k') | chromecast/renderer/media/video_pipeline_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698