summaryrefslogtreecommitdiffstats
path: root/content/browser/media
diff options
context:
space:
mode:
authorwatk <watk@chromium.org>2016-02-17 18:22:19 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-18 02:23:19 +0000
commitdee516f91d460baf825f25503063a898ec3aaf3a (patch)
tree6ddd13c49f5b3548c28771377dff49a325f5b302 /content/browser/media
parent8fb3a4aee13f5299f4fb27d879b1fd1f07a5ae15 (diff)
downloadchromium_src-dee516f91d460baf825f25503063a898ec3aaf3a.zip
chromium_src-dee516f91d460baf825f25503063a898ec3aaf3a.tar.gz
chromium_src-dee516f91d460baf825f25503063a898ec3aaf3a.tar.bz2
Enable Android SurfaceView fullscreen video with WMPI
This CL enables SurfaceView fullscreen video with the unified media pipeline in cases where we use the AVDA deferred rendering strategy today. * There's a new media interface called SurfaceManager with two methods: CreateFullscreenSurface() and NaturalSizeChanged(). * SurfaceManager is implemented by RendererSurfaceViewManager, which is a RenderFrameObserver, and BrowserSurfaceViewManager, which is created for each RenderFrame by MediaWebContentsObserverAndroid. * BrowserSurfaceViewManager creates a ContentVideoView in response to a CreateFullscreenSurface message, and registers it in a surface map that the decoder can look up in the GPU process. * WMPI interacts with SurfaceManager on behalf of the decoder. It passes GpuVideoDecoder a callback for requesting surfaces which it calls before initializing VDAs. * In response to the callback, if the player is in fullscreen WMPI will pass the request to the SurfaceManager which will return the surface id to GVD. If the player is not in fullscreen WMPI will return a null surface id. * When GVD gets a surface id back it completes its initialization by calling VDA::Initialize with the surface id and the VDA will render to the given surface. * WMPI records that it got a surface request callback so that it knows that future fullscreen transitions will require a restart of the decoder in order to switch surfaces. * A future CL will allow us to switch the surface dynamically without requiring a restart. BUG=533630 Review URL: https://codereview.chromium.org/1655083002 Cr-Commit-Position: refs/heads/master@{#376068}
Diffstat (limited to 'content/browser/media')
-rw-r--r--content/browser/media/android/browser_surface_view_manager.cc86
-rw-r--r--content/browser/media/android/browser_surface_view_manager.h53
-rw-r--r--content/browser/media/android/media_web_contents_observer_android.cc35
-rw-r--r--content/browser/media/android/media_web_contents_observer_android.h19
4 files changed, 189 insertions, 4 deletions
diff --git a/content/browser/media/android/browser_surface_view_manager.cc b/content/browser/media/android/browser_surface_view_manager.cc
new file mode 100644
index 0000000..f171a16
--- /dev/null
+++ b/content/browser/media/android/browser_surface_view_manager.cc
@@ -0,0 +1,86 @@
+// Copyright 2016 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 "content/browser/media/android/browser_surface_view_manager.h"
+
+#include "content/browser/android/child_process_launcher_android.h"
+#include "content/browser/android/content_view_core_impl.h"
+#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/media/surface_view_manager_messages_android.h"
+#include "content/public/browser/render_frame_host.h"
+#include "media/base/surface_manager.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+BrowserSurfaceViewManager::BrowserSurfaceViewManager(
+ RenderFrameHost* render_frame_host)
+ : render_frame_host_(render_frame_host),
+ surface_id_(media::SurfaceManager::kNoSurfaceID) {}
+
+BrowserSurfaceViewManager::~BrowserSurfaceViewManager() {}
+
+void BrowserSurfaceViewManager::SetVideoSurface(
+ gfx::ScopedJavaSurface surface) {
+ if (surface.IsEmpty()) {
+ DCHECK_NE(surface_id_, media::SurfaceManager::kNoSurfaceID);
+ GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
+ UnregisterViewSurface(surface_id_);
+ surface_id_ = media::SurfaceManager::kNoSurfaceID;
+ } else {
+ // We mainly use the surface tracker to allocate a surface id for us. The
+ // lookup will go through the Android specific path and get the java
+ // surface directly, so there's no need to add a valid native widget here.
+ surface_id_ = GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(
+ gfx::kNullAcceleratedWidget);
+ RegisterViewSurface(surface_id_, surface.j_surface().obj());
+ SendSurfaceID(surface_id_);
+ }
+}
+
+void BrowserSurfaceViewManager::DidExitFullscreen(bool release_media_player) {
+ DVLOG(3) << __FUNCTION__;
+ content_video_view_.reset();
+}
+
+void BrowserSurfaceViewManager::OnCreateFullscreenSurface(
+ const gfx::Size& video_natural_size) {
+ // It's valid to get this call if we already own the fullscreen view. We just
+ // return the existing surface id.
+ if (content_video_view_) {
+ // Send the surface now if we have it. Otherwise it will be returned by
+ // |SetVideoSurface|.
+ if (surface_id_ != media::SurfaceManager::kNoSurfaceID) {
+ SendSurfaceID(surface_id_);
+ OnNaturalSizeChanged(video_natural_size);
+ return;
+ }
+ }
+
+ // If we don't own the fullscreen view, but one exists, it means another
+ // WebContents has it. Ignore this request and return a null surface id.
+ if (ContentVideoView::GetInstance()) {
+ SendSurfaceID(media::SurfaceManager::kNoSurfaceID);
+ return;
+ }
+
+ ContentViewCore* cvc = ContentViewCore::FromWebContents(
+ WebContents::FromRenderFrameHost(render_frame_host_));
+ content_video_view_.reset(new ContentVideoView(this, cvc));
+ OnNaturalSizeChanged(video_natural_size);
+}
+
+void BrowserSurfaceViewManager::OnNaturalSizeChanged(const gfx::Size& size) {
+ if (content_video_view_)
+ content_video_view_->OnVideoSizeChanged(size.width(), size.height());
+}
+
+bool BrowserSurfaceViewManager::SendSurfaceID(int surface_id) {
+ return render_frame_host_->Send(
+ new SurfaceViewManagerMsg_FullscreenSurfaceCreated(
+ render_frame_host_->GetRoutingID(), surface_id));
+}
+
+} // namespace content
diff --git a/content/browser/media/android/browser_surface_view_manager.h b/content/browser/media/android/browser_surface_view_manager.h
new file mode 100644
index 0000000..df6b2594
--- /dev/null
+++ b/content/browser/media/android/browser_surface_view_manager.h
@@ -0,0 +1,53 @@
+// Copyright 2016 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.
+
+#ifndef CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_SURFACE_VIEW_MANAGER_H_
+#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_SURFACE_VIEW_MANAGER_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/browser/android/content_video_view.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+// BrowserSurfaceViewManager creates and owns a ContentVideoView on behalf of
+// a fullscreen media player. Its SurfaceView is registered so that a decoder
+// in the GPU process can look it up and render to it.
+class CONTENT_EXPORT BrowserSurfaceViewManager
+ : public ContentVideoView::Client {
+ public:
+ explicit BrowserSurfaceViewManager(RenderFrameHost* render_frame_host);
+ ~BrowserSurfaceViewManager();
+
+ // ContentVideoView::Client overrides.
+ void SetVideoSurface(gfx::ScopedJavaSurface surface) override;
+ void DidExitFullscreen(bool release_media_player) override;
+
+ void OnCreateFullscreenSurface(const gfx::Size& video_natural_size);
+ void OnNaturalSizeChanged(const gfx::Size& size);
+
+ private:
+ // Send a message to return the surface id to the caller.
+ bool SendSurfaceID(int surface_id);
+
+ RenderFrameHost* const render_frame_host_;
+
+ // The surface id of the ContentVideoView surface.
+ int surface_id_;
+
+ // The fullscreen view that contains a SurfaceView.
+ scoped_ptr<ContentVideoView> content_video_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserSurfaceViewManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_SURFACE_VIEW_MANAGER_H_
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 29f4b18..819c6b4 100644
--- a/content/browser/media/android/media_web_contents_observer_android.cc
+++ b/content/browser/media/android/media_web_contents_observer_android.cc
@@ -6,6 +6,7 @@
#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/browser_surface_view_manager.h"
#include "content/browser/media/android/media_session.h"
#include "content/browser/media/android/media_session_controller.h"
#include "content/browser/media/android/media_session_observer.h"
@@ -14,6 +15,7 @@
#include "content/common/media/media_player_delegate_messages.h"
#include "content/common/media/media_player_messages_android.h"
#include "content/common/media/media_session_messages_android.h"
+#include "content/common/media/surface_view_manager_messages_android.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_message_macros.h"
@@ -67,6 +69,19 @@ MediaWebContentsObserverAndroid::GetMediaSessionManager(
return manager;
}
+BrowserSurfaceViewManager*
+MediaWebContentsObserverAndroid::GetSurfaceViewManager(
+ RenderFrameHost* render_frame_host) {
+ auto it = surface_view_managers_.find(render_frame_host);
+ if (it != surface_view_managers_.end())
+ return it->second;
+
+ BrowserSurfaceViewManager* manager =
+ new BrowserSurfaceViewManager(render_frame_host);
+ surface_view_managers_.set(render_frame_host, make_scoped_ptr(manager));
+ return manager;
+}
+
void MediaWebContentsObserverAndroid::SuspendAllMediaPlayers() {
web_contents()->ForEachFrame(
base::Bind(&SuspendAllMediaPlayersInRenderFrame));
@@ -109,6 +124,7 @@ void MediaWebContentsObserverAndroid::RenderFrameDeleted(
// detaching CDMs from media players yet. See http://crbug.com/330324
media_player_managers_.erase(render_frame_host);
media_session_managers_.erase(render_frame_host);
+ surface_view_managers_.erase(render_frame_host);
// TODO(xhwang): Currently MediaWebContentsObserver, BrowserMediaPlayerManager
// and BrowserCdmManager all run on browser UI thread. So this call is okay.
@@ -140,6 +156,9 @@ bool MediaWebContentsObserverAndroid::OnMessageReceived(
if (OnMediaSessionMessageReceived(msg, render_frame_host))
return true;
+ if (OnSurfaceViewManagerMessageReceived(msg, render_frame_host))
+ return true;
+
return false;
}
@@ -238,6 +257,22 @@ bool MediaWebContentsObserverAndroid::OnMediaSessionMessageReceived(
return handled;
}
+bool MediaWebContentsObserverAndroid::OnSurfaceViewManagerMessageReceived(
+ const IPC::Message& msg,
+ RenderFrameHost* render_frame_host) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserverAndroid, msg)
+ IPC_MESSAGE_FORWARD(SurfaceViewManagerHostMsg_CreateFullscreenSurface,
+ GetSurfaceViewManager(render_frame_host),
+ BrowserSurfaceViewManager::OnCreateFullscreenSurface)
+ IPC_MESSAGE_FORWARD(SurfaceViewManagerHostMsg_NaturalSizeChanged,
+ GetSurfaceViewManager(render_frame_host),
+ BrowserSurfaceViewManager::OnNaturalSizeChanged)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
void MediaWebContentsObserverAndroid::OnSetCdm(
RenderFrameHost* render_frame_host,
int player_id,
diff --git a/content/browser/media/android/media_web_contents_observer_android.h b/content/browser/media/android/media_web_contents_observer_android.h
index 63b17da..e8e3650 100644
--- a/content/browser/media/android/media_web_contents_observer_android.h
+++ b/content/browser/media/android/media_web_contents_observer_android.h
@@ -18,6 +18,7 @@ namespace content {
class BrowserCdmManager;
class BrowserMediaPlayerManager;
class BrowserMediaSessionManager;
+class BrowserSurfaceViewManager;
class MediaSessionController;
// This class adds Android specific extensions to the MediaWebContentsObserver.
@@ -31,13 +32,15 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
static MediaWebContentsObserverAndroid* FromWebContents(
WebContents* web_contents);
- // Gets the media player or media session manager associated with the given
- // |render_frame_host| respectively. Creates a new one if it doesn't exist.
- // The caller doesn't own the returned pointer.
+ // Gets one of the managers associated with the given |render_frame_host|.
+ // Creates a new one if it doesn't exist. The caller doesn't own the
+ // returned pointer.
BrowserMediaPlayerManager* GetMediaPlayerManager(
RenderFrameHost* render_frame_host);
BrowserMediaSessionManager* GetMediaSessionManager(
RenderFrameHost* render_frame_host);
+ BrowserSurfaceViewManager* GetSurfaceViewManager(
+ RenderFrameHost* render_frame_host);
// Called by the WebContents when a tab has been closed but may still be
// available for "undo" -- indicates that all media players (even audio only
@@ -59,7 +62,7 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
void OnFrameInfoUpdated();
#endif // defined(VIDEO_HOLE)
- // MediaWebContentsObserverAndroid overrides.
+ // MediaWebContentsObserver overrides.
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
bool OnMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host) override;
@@ -91,6 +94,9 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
bool OnMediaSessionMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host);
+ bool OnSurfaceViewManagerMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host);
+
void OnSetCdm(RenderFrameHost* render_frame_host, int player_id, int cdm_id);
// Map from RenderFrameHost* to BrowserMediaPlayerManager.
@@ -110,6 +116,11 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
std::map<MediaPlayerId, scoped_ptr<MediaSessionController>>;
MediaSessionMap media_session_map_;
+ using SurfaceViewManagerMap =
+ base::ScopedPtrHashMap<RenderFrameHost*,
+ scoped_ptr<BrowserSurfaceViewManager>>;
+ SurfaceViewManagerMap surface_view_managers_;
+
DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserverAndroid);
};