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

Unified Diff: content/browser/media/android/media_web_contents_observer_android.cc

Issue 1570043002: Implement MediaSession on top of the WebMediaPlayerDelegate. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@media_session
Patch Set: Created 4 years, 11 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
Index: content/browser/media/android/media_web_contents_observer_android.cc
diff --git a/content/browser/media/android/media_web_contents_observer_android.cc b/content/browser/media/android/media_web_contents_observer_android.cc
index 2bd332681c614786dc1d33fa59fd8669995b2221..5e1ea718b447cdc393d2c93c8e0825120d607ddd 100644
--- a/content/browser/media/android/media_web_contents_observer_android.cc
+++ b/content/browser/media/android/media_web_contents_observer_android.cc
@@ -8,6 +8,7 @@
#include "base/stl_util.h"
#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/media/android/browser_media_session_manager.h"
+#include "content/browser/media/android/media_session.h"
#include "content/browser/media/android/media_session_observer.h"
#include "content/browser/media/cdm/browser_cdm_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -21,11 +22,81 @@
namespace content {
+class MediaSessionController : public MediaSessionObserver {
mlamouri (slow - plz ping) 2016/01/14 15:43:08 Maybe this could be in a separate file?
DaleCurtis 2016/01/14 18:21:18 Yeah, I was thinking the same since it ended up la
+ public:
+ MediaSessionController(const WebContentsObserver::MediaPlayerId& id,
+ MediaWebContentsObserver* media_web_contents_observer)
+ : id_(id), media_web_contents_observer_(media_web_contents_observer) {}
+
+ // Clients must call this after construction and destroy the controller if it
+ // returns false.
+ bool Initialize(bool has_video, bool has_audio, base::TimeDelta duration) {
+ // These objects are only created on the UI thread, so this is safe.
+ static uint32_t player_id = 0;
+ player_id_ = static_cast<int>(player_id++);
+
+ // Minimal duration of a player in order to be considered as Content type.
+ const base::TimeDelta kMinimumDurationForContent =
+ base::TimeDelta::FromSeconds(5);
+
+ const MediaSession::Type media_session_type =
+ duration == base::TimeDelta() || duration > kMinimumDurationForContent
+ ? MediaSession::Type::Content
+ : MediaSession::Type::Transient;
+
+ // If a session can't be created, force a pause immediately.
+ if (!MediaSession::Get(media_web_contents_observer_->web_contents())
+ ->AddPlayer(this, player_id_, media_session_type)) {
+ OnSuspend(player_id_);
+ return false;
+ }
+
+ return true;
+ }
+
+ ~MediaSessionController() {
+ MediaSession::Get(media_web_contents_observer_->web_contents())
+ ->RemovePlayer(this, player_id_);
+ }
+
+ void OnSuspend(int player_id) {
+ DCHECK_EQ(player_id_, player_id);
+ media_web_contents_observer_->Send(
+ new FrameMsg_MediaDelegatePause(id_.first->GetRoutingID(), id_.second));
+ }
+
+ void OnResume(int player_id) {
+ DCHECK_EQ(player_id_, player_id);
+ media_web_contents_observer_->Send(
+ new FrameMsg_MediaDelegatePlay(id_.first->GetRoutingID(), id_.second));
+ }
+
+ void PausePlayback() {
+ MediaSession* session =
+ MediaSession::Get(media_web_contents_observer_->web_contents());
+ // TODO(dalecurtis, mlamouri): This seems odd, if we don't check suspend of
+ // the entire session, notifying a pause will DCHECK in mediasession.cc:146.
+ if (!session->IsSuspended())
mlamouri (slow - plz ping) 2016/01/14 15:43:08 How do you end up with a suspended session that pa
DaleCurtis 2016/01/14 18:21:18 This is due to the delegate sending a "pause" ack
mlamouri (slow - plz ping) 2016/01/19 16:59:11 zqzhang@ has been working on issues related to tha
+ session->OnPlayerPaused(this, player_id_);
+ }
+
+ private:
+ const WebContentsObserver::MediaPlayerId id_;
+ MediaWebContentsObserver* const media_web_contents_observer_;
+ int player_id_ = 0;
+ bool initialize_failed_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionController);
+};
+
MediaWebContentsObserverAndroid::MediaWebContentsObserverAndroid(
WebContents* web_contents)
: MediaWebContentsObserver(web_contents) {}
-MediaWebContentsObserverAndroid::~MediaWebContentsObserverAndroid() {}
+MediaWebContentsObserverAndroid::~MediaWebContentsObserverAndroid() {
+ // Clear active sessions before destructing the observer.
+ media_session_map_.clear();
+}
// static
MediaWebContentsObserverAndroid*
@@ -93,6 +164,10 @@ void MediaWebContentsObserverAndroid::RenderFrameDeleted(
bool MediaWebContentsObserverAndroid::OnMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
+ // Receive play/pause/destroyed messages, but don't mark as processed so they
+ // are also handled by MediaWebContentsObserver.
+ OnMediaPlayerDelegateMessageReceived(msg, render_frame_host);
+
if (MediaWebContentsObserver::OnMessageReceived(msg, render_frame_host))
return true;
@@ -105,6 +180,21 @@ bool MediaWebContentsObserverAndroid::OnMessageReceived(
return false;
}
+void MediaWebContentsObserverAndroid::OnMediaPlayerDelegateMessageReceived(
+ const IPC::Message& msg,
+ RenderFrameHost* render_frame_host) {
+ // TODO(dalecurtis): These should no longer be FrameHostMsg.
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MediaWebContentsObserverAndroid, msg,
+ render_frame_host)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_MediaDestroyedNotification,
+ OnMediaDestroyedNotification)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPlayingNotification,
+ OnMediaPlayingNotification)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification,
+ OnMediaPausedNotification)
+ IPC_END_MESSAGE_MAP()
+}
+
bool MediaWebContentsObserverAndroid::OnMediaPlayerMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
@@ -203,4 +293,51 @@ void MediaWebContentsObserverAndroid::OnSetCdm(
media_player->SetCdm(cdm);
}
+void MediaWebContentsObserverAndroid::OnMediaDestroyedNotification(
mlamouri (slow - plz ping) 2016/01/14 15:43:08 Do we destroy the media as soon as it reached the
DaleCurtis 2016/01/14 18:21:18 No, this is only called when the WMP is being dest
+ RenderFrameHost* render_frame_host,
+ int64_t player_cookie) {
+ media_session_map_.erase(MediaPlayerId(render_frame_host, player_cookie));
+}
+
+void MediaWebContentsObserverAndroid::OnMediaPlayingNotification(
mlamouri (slow - plz ping) 2016/01/14 15:43:08 Are we going to call this when the media _starts_
DaleCurtis 2016/01/14 18:21:18 This is only called when status changes to play.
mlamouri (slow - plz ping) 2016/01/19 16:59:11 Does that match the 'playing' event?
DaleCurtis 2016/01/20 00:43:58 Yes
+ RenderFrameHost* render_frame_host,
+ int64_t player_cookie,
+ bool has_video,
+ bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration) {
+ // Don't setup a media session for remote playback instances.
+ if (is_remote)
+ return;
+
+ const MediaPlayerId id(render_frame_host, player_cookie);
+ scoped_ptr<MediaSessionController> controller(
+ new MediaSessionController(id, this));
+
+ // If initialize fails, the controller should be destroyed and a new one
+ // attempted later after another playback attempt occurs.
+ if (!controller->Initialize(has_video, has_audio, duration))
+ return;
+
+ media_session_map_[id] = std::move(controller);
+}
+
+void MediaWebContentsObserverAndroid::OnMediaPausedNotification(
+ RenderFrameHost* render_frame_host,
+ int64_t player_cookie,
+ bool reached_end_of_stream) {
+ // Drop the session if playback completes normally.
+ if (reached_end_of_stream) {
+ OnMediaDestroyedNotification(render_frame_host, player_cookie);
+ return;
+ }
+
+ auto it =
+ media_session_map_.find(MediaPlayerId(render_frame_host, player_cookie));
+ if (it == media_session_map_.end())
+ return;
+
+ it->second->PausePlayback();
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698