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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/media/android/media_web_contents_observer_android.h" 5 #include "content/browser/media/android/media_web_contents_observer_android.h"
6 6
7 #include "base/memory/scoped_ptr.h" 7 #include "base/memory/scoped_ptr.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "content/browser/media/android/browser_media_player_manager.h" 9 #include "content/browser/media/android/browser_media_player_manager.h"
10 #include "content/browser/media/android/browser_media_session_manager.h" 10 #include "content/browser/media/android/browser_media_session_manager.h"
11 #include "content/browser/media/android/media_session.h"
11 #include "content/browser/media/android/media_session_observer.h" 12 #include "content/browser/media/android/media_session_observer.h"
12 #include "content/browser/media/cdm/browser_cdm_manager.h" 13 #include "content/browser/media/cdm/browser_cdm_manager.h"
13 #include "content/browser/web_contents/web_contents_impl.h" 14 #include "content/browser/web_contents/web_contents_impl.h"
14 #include "content/common/frame_messages.h" 15 #include "content/common/frame_messages.h"
15 #include "content/common/media/media_player_messages_android.h" 16 #include "content/common/media/media_player_messages_android.h"
16 #include "content/common/media/media_session_messages_android.h" 17 #include "content/common/media/media_session_messages_android.h"
17 #include "content/public/browser/render_frame_host.h" 18 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/web_contents.h" 19 #include "content/public/browser/web_contents.h"
19 #include "ipc/ipc_message_macros.h" 20 #include "ipc/ipc_message_macros.h"
20 #include "media/base/android/media_player_android.h" 21 #include "media/base/android/media_player_android.h"
21 22
22 namespace content { 23 namespace content {
23 24
25 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
26 public:
27 MediaSessionController(const WebContentsObserver::MediaPlayerId& id,
28 MediaWebContentsObserver* media_web_contents_observer)
29 : id_(id), media_web_contents_observer_(media_web_contents_observer) {}
30
31 // Clients must call this after construction and destroy the controller if it
32 // returns false.
33 bool Initialize(bool has_video, bool has_audio, base::TimeDelta duration) {
34 // These objects are only created on the UI thread, so this is safe.
35 static uint32_t player_id = 0;
36 player_id_ = static_cast<int>(player_id++);
37
38 // Minimal duration of a player in order to be considered as Content type.
39 const base::TimeDelta kMinimumDurationForContent =
40 base::TimeDelta::FromSeconds(5);
41
42 const MediaSession::Type media_session_type =
43 duration == base::TimeDelta() || duration > kMinimumDurationForContent
44 ? MediaSession::Type::Content
45 : MediaSession::Type::Transient;
46
47 // If a session can't be created, force a pause immediately.
48 if (!MediaSession::Get(media_web_contents_observer_->web_contents())
49 ->AddPlayer(this, player_id_, media_session_type)) {
50 OnSuspend(player_id_);
51 return false;
52 }
53
54 return true;
55 }
56
57 ~MediaSessionController() {
58 MediaSession::Get(media_web_contents_observer_->web_contents())
59 ->RemovePlayer(this, player_id_);
60 }
61
62 void OnSuspend(int player_id) {
63 DCHECK_EQ(player_id_, player_id);
64 media_web_contents_observer_->Send(
65 new FrameMsg_MediaDelegatePause(id_.first->GetRoutingID(), id_.second));
66 }
67
68 void OnResume(int player_id) {
69 DCHECK_EQ(player_id_, player_id);
70 media_web_contents_observer_->Send(
71 new FrameMsg_MediaDelegatePlay(id_.first->GetRoutingID(), id_.second));
72 }
73
74 void PausePlayback() {
75 MediaSession* session =
76 MediaSession::Get(media_web_contents_observer_->web_contents());
77 // TODO(dalecurtis, mlamouri): This seems odd, if we don't check suspend of
78 // the entire session, notifying a pause will DCHECK in mediasession.cc:146.
79 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
80 session->OnPlayerPaused(this, player_id_);
81 }
82
83 private:
84 const WebContentsObserver::MediaPlayerId id_;
85 MediaWebContentsObserver* const media_web_contents_observer_;
86 int player_id_ = 0;
87 bool initialize_failed_ = false;
88
89 DISALLOW_COPY_AND_ASSIGN(MediaSessionController);
90 };
91
24 MediaWebContentsObserverAndroid::MediaWebContentsObserverAndroid( 92 MediaWebContentsObserverAndroid::MediaWebContentsObserverAndroid(
25 WebContents* web_contents) 93 WebContents* web_contents)
26 : MediaWebContentsObserver(web_contents) {} 94 : MediaWebContentsObserver(web_contents) {}
27 95
28 MediaWebContentsObserverAndroid::~MediaWebContentsObserverAndroid() {} 96 MediaWebContentsObserverAndroid::~MediaWebContentsObserverAndroid() {
97 // Clear active sessions before destructing the observer.
98 media_session_map_.clear();
99 }
29 100
30 // static 101 // static
31 MediaWebContentsObserverAndroid* 102 MediaWebContentsObserverAndroid*
32 MediaWebContentsObserverAndroid::FromWebContents(WebContents* web_contents) { 103 MediaWebContentsObserverAndroid::FromWebContents(WebContents* web_contents) {
33 return static_cast<MediaWebContentsObserverAndroid*>( 104 return static_cast<MediaWebContentsObserverAndroid*>(
34 static_cast<WebContentsImpl*>(web_contents) 105 static_cast<WebContentsImpl*>(web_contents)
35 ->media_web_contents_observer()); 106 ->media_web_contents_observer());
36 } 107 }
37 108
38 BrowserMediaPlayerManager* 109 BrowserMediaPlayerManager*
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 // BrowserCdmManager run on a different thread. 157 // BrowserCdmManager run on a different thread.
87 BrowserCdmManager* browser_cdm_manager = 158 BrowserCdmManager* browser_cdm_manager =
88 BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID()); 159 BrowserCdmManager::FromProcess(render_frame_host->GetProcess()->GetID());
89 if (browser_cdm_manager) 160 if (browser_cdm_manager)
90 browser_cdm_manager->RenderFrameDeleted(render_frame_host->GetRoutingID()); 161 browser_cdm_manager->RenderFrameDeleted(render_frame_host->GetRoutingID());
91 } 162 }
92 163
93 bool MediaWebContentsObserverAndroid::OnMessageReceived( 164 bool MediaWebContentsObserverAndroid::OnMessageReceived(
94 const IPC::Message& msg, 165 const IPC::Message& msg,
95 RenderFrameHost* render_frame_host) { 166 RenderFrameHost* render_frame_host) {
167 // Receive play/pause/destroyed messages, but don't mark as processed so they
168 // are also handled by MediaWebContentsObserver.
169 OnMediaPlayerDelegateMessageReceived(msg, render_frame_host);
170
96 if (MediaWebContentsObserver::OnMessageReceived(msg, render_frame_host)) 171 if (MediaWebContentsObserver::OnMessageReceived(msg, render_frame_host))
97 return true; 172 return true;
98 173
99 if (OnMediaPlayerMessageReceived(msg, render_frame_host)) 174 if (OnMediaPlayerMessageReceived(msg, render_frame_host))
100 return true; 175 return true;
101 176
102 if (OnMediaPlayerSetCdmMessageReceived(msg, render_frame_host)) 177 if (OnMediaPlayerSetCdmMessageReceived(msg, render_frame_host))
103 return true; 178 return true;
104 179
105 return false; 180 return false;
106 } 181 }
107 182
183 void MediaWebContentsObserverAndroid::OnMediaPlayerDelegateMessageReceived(
184 const IPC::Message& msg,
185 RenderFrameHost* render_frame_host) {
186 // TODO(dalecurtis): These should no longer be FrameHostMsg.
187 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MediaWebContentsObserverAndroid, msg,
188 render_frame_host)
189 IPC_MESSAGE_HANDLER(FrameHostMsg_MediaDestroyedNotification,
190 OnMediaDestroyedNotification)
191 IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPlayingNotification,
192 OnMediaPlayingNotification)
193 IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification,
194 OnMediaPausedNotification)
195 IPC_END_MESSAGE_MAP()
196 }
197
108 bool MediaWebContentsObserverAndroid::OnMediaPlayerMessageReceived( 198 bool MediaWebContentsObserverAndroid::OnMediaPlayerMessageReceived(
109 const IPC::Message& msg, 199 const IPC::Message& msg,
110 RenderFrameHost* render_frame_host) { 200 RenderFrameHost* render_frame_host) {
111 bool handled = true; 201 bool handled = true;
112 IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserverAndroid, msg) 202 IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserverAndroid, msg)
113 IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_EnterFullscreen, 203 IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_EnterFullscreen,
114 GetMediaPlayerManager(render_frame_host), 204 GetMediaPlayerManager(render_frame_host),
115 BrowserMediaPlayerManager::OnEnterFullscreen) 205 BrowserMediaPlayerManager::OnEnterFullscreen)
116 IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Initialize, 206 IPC_MESSAGE_FORWARD(MediaPlayerHostMsg_Initialize,
117 GetMediaPlayerManager(render_frame_host), 207 GetMediaPlayerManager(render_frame_host),
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 if (!cdm) { 286 if (!cdm) {
197 NOTREACHED() << "OnSetCdm: CDM not found for " << cdm_id; 287 NOTREACHED() << "OnSetCdm: CDM not found for " << cdm_id;
198 return; 288 return;
199 } 289 }
200 290
201 // TODO(xhwang): This could possibly fail. In that case we should reject the 291 // TODO(xhwang): This could possibly fail. In that case we should reject the
202 // promise. 292 // promise.
203 media_player->SetCdm(cdm); 293 media_player->SetCdm(cdm);
204 } 294 }
205 295
296 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
297 RenderFrameHost* render_frame_host,
298 int64_t player_cookie) {
299 media_session_map_.erase(MediaPlayerId(render_frame_host, player_cookie));
300 }
301
302 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
303 RenderFrameHost* render_frame_host,
304 int64_t player_cookie,
305 bool has_video,
306 bool has_audio,
307 bool is_remote,
308 base::TimeDelta duration) {
309 // Don't setup a media session for remote playback instances.
310 if (is_remote)
311 return;
312
313 const MediaPlayerId id(render_frame_host, player_cookie);
314 scoped_ptr<MediaSessionController> controller(
315 new MediaSessionController(id, this));
316
317 // If initialize fails, the controller should be destroyed and a new one
318 // attempted later after another playback attempt occurs.
319 if (!controller->Initialize(has_video, has_audio, duration))
320 return;
321
322 media_session_map_[id] = std::move(controller);
323 }
324
325 void MediaWebContentsObserverAndroid::OnMediaPausedNotification(
326 RenderFrameHost* render_frame_host,
327 int64_t player_cookie,
328 bool reached_end_of_stream) {
329 // Drop the session if playback completes normally.
330 if (reached_end_of_stream) {
331 OnMediaDestroyedNotification(render_frame_host, player_cookie);
332 return;
333 }
334
335 auto it =
336 media_session_map_.find(MediaPlayerId(render_frame_host, player_cookie));
337 if (it == media_session_map_.end())
338 return;
339
340 it->second->PausePlayback();
341 }
342
206 } // namespace content 343 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698