summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/renderer/render_view_impl.cc15
-rw-r--r--content/renderer/render_view_impl.h17
-rw-r--r--media/base/android/media_player_bridge.cc1
-rw-r--r--webkit/media/android/stream_texture_factory_android.h56
-rw-r--r--webkit/media/android/webmediaplayer_android.cc95
-rw-r--r--webkit/media/android/webmediaplayer_android.h48
-rw-r--r--webkit/media/android/webmediaplayer_manager_android.cc50
-rw-r--r--webkit/media/android/webmediaplayer_manager_android.h53
-rw-r--r--webkit/media/webkit_media.gypi3
9 files changed, 324 insertions, 14 deletions
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index f37da15..b8cf211 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -188,6 +188,7 @@
#if defined(OS_ANDROID)
#include "webkit/media/android/webmediaplayer_android.h"
+#include "webkit/media/android/webmediaplayer_manager_android.h"
#elif defined(OS_WIN)
// TODO(port): these files are currently Windows only because they concern:
// * theming
@@ -611,6 +612,11 @@ RenderViewImpl::RenderViewImpl(
new TextInputClientObserver(this);
#endif // defined(OS_MACOSX)
+#if defined(OS_ANDROID)
+ media_player_manager_.reset(
+ new webkit_media::WebMediaPlayerManagerAndroid());
+#endif
+
// The next group of objects all implement RenderViewObserver, so are deleted
// along with the RenderView automatically.
devtools_agent_ = new DevToolsAgent(this);
@@ -2302,8 +2308,10 @@ WebMediaPlayer* RenderViewImpl::createMediaPlayer(
RenderViewObserver, observers_, WillCreateMediaPlayer(frame, client));
#if defined(OS_ANDROID)
+ // TODO(qinmin): upstream the implementation of StreamTextureFactoryImpl
+ // to replace the NULL param here.
return new webkit_media::WebMediaPlayerAndroid(
- client, cookieJar(frame));
+ frame, client, cookieJar(frame), media_player_manager_.get(), NULL);
#endif
media::MessageLoopFactory* message_loop_factory =
@@ -5040,6 +5048,11 @@ void RenderViewImpl::DidHandleTouchEvent(const WebTouchEvent& event) {
void RenderViewImpl::OnWasHidden() {
RenderWidget::OnWasHidden();
+#if defined(OS_ANDROID)
+ // Inform WebMediaPlayerManagerAndroid to release all media player resources.
+ media_player_manager_->ReleaseMediaResources();
+#endif
+
if (webview()) {
webview()->settings()->setMinimumTimerInterval(
webkit_glue::kBackgroundTabTimerInterval);
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 64d4f39..9d8fdb7 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -122,6 +122,12 @@ class ImageResourceFetcher;
class ResourceFetcher;
}
+#if defined(OS_ANDROID)
+namespace webkit_media {
+class WebMediaPlayerManagerAndroid;
+}
+#endif
+
namespace WebKit {
class WebApplicationCacheHost;
class WebApplicationCacheHostClient;
@@ -244,6 +250,12 @@ class RenderViewImpl : public RenderWidget,
return mouse_lock_dispatcher_;
}
+#if defined(OS_ANDROID)
+ webkit_media::WebMediaPlayerManagerAndroid* media_player_manager() {
+ return media_player_manager_.get();
+ }
+#endif
+
WebKit::WebPeerConnectionHandler* CreatePeerConnectionHandler(
WebKit::WebPeerConnectionHandlerClient* client);
WebKit::WebPeerConnection00Handler* CreatePeerConnectionHandlerJsep(
@@ -1365,6 +1377,11 @@ class RenderViewImpl : public RenderWidget,
// Wraps the |webwidget_| as a MouseLockDispatcher::LockTarget interface.
scoped_ptr<MouseLockDispatcher::LockTarget> webwidget_mouse_lock_target_;
+#if defined(OS_ANDROID)
+ // The media player manager for managing all the media players on this view.
+ scoped_ptr<webkit_media::WebMediaPlayerManagerAndroid> media_player_manager_;
+#endif
+
// Plugins -------------------------------------------------------------------
// All the currently active plugin delegates for this RenderView; kept so
diff --git a/media/base/android/media_player_bridge.cc b/media/base/android/media_player_bridge.cc
index a494777..44d13b6 100644
--- a/media/base/android/media_player_bridge.cc
+++ b/media/base/android/media_player_bridge.cc
@@ -76,6 +76,7 @@ MediaPlayerBridge::MediaPlayerBridge() {
}
MediaPlayerBridge::~MediaPlayerBridge() {
+ SetVideoSurface(NULL);
CallVoidMethod("release");
}
diff --git a/webkit/media/android/stream_texture_factory_android.h b/webkit/media/android/stream_texture_factory_android.h
new file mode 100644
index 0000000..9ef4e4d
--- /dev/null
+++ b/webkit/media/android/stream_texture_factory_android.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 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 WEBKIT_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_H_
+#define WEBKIT_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_H_
+#pragma once
+
+namespace WebKit {
+class WebStreamTextureClient;
+}
+
+namespace webkit_media {
+
+// The proxy class for the gpu thread to notify the compositor thread
+// when a new video frame is available.
+class StreamTextureProxy {
+ public:
+ virtual ~StreamTextureProxy() {}
+
+ // Initialize the the stream_id, texture width and height. This should
+ // be called on the compositor thread.
+ virtual bool Initialize(int stream_id, int width, int height) = 0;
+
+ virtual bool IsInitialized() = 0;
+
+ // Setting the target for callback when a frame is available. This function
+ // could be called on both the main thread and the compositor thread.
+ virtual void SetClient(WebKit::WebStreamTextureClient* client) = 0;
+};
+
+
+// Factory class for managing the stream texture.
+class StreamTextureFactory {
+ public:
+ virtual ~StreamTextureFactory() {}
+
+ // Create the StreamTextureProxy object.
+ virtual StreamTextureProxy* CreateProxy() = 0;
+
+ // Send an IPC message to the browser process to request a java surface
+ // object for the given stream_id. After the the surface is created,
+ // it will be passed back to the WebMediaPlayerAndroid object identified by
+ // the player_id.
+ virtual void EstablishPeer(int stream_id, int player_id) = 0;
+
+ // Create the streamTexture and return the stream Id and set the texture id.
+ virtual unsigned CreateStreamTexture(unsigned* texture_id) = 0;
+
+ // Destroy the streamTexture for the given texture Id.
+ virtual void DestroyStreamTexture(unsigned texture_id) = 0;
+};
+
+} // namespace webkit_media
+
+#endif // WEBKIT_MEDIA_ANDROID_STREAM_TEXTURE_FACTORY_ANDROID_H_
diff --git a/webkit/media/android/webmediaplayer_android.cc b/webkit/media/android/webmediaplayer_android.cc
index 1b99ebb..faaadaf 100644
--- a/webkit/media/android/webmediaplayer_android.cc
+++ b/webkit/media/android/webmediaplayer_android.cc
@@ -13,10 +13,14 @@
#include "base/utf_string_conversions.h"
#include "media/base/android/media_player_bridge.h"
#include "net/base/mime_util.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayerClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCookieJar.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
+#include "webkit/media/android/stream_texture_factory_android.h"
+#include "webkit/media/android/webmediaplayer_manager_android.h"
#include "webkit/media/android/webmediaplayer_proxy_android.h"
#include "webkit/media/webmediaplayer_util.h"
#include "webkit/media/webvideoframe_impl.h"
@@ -33,6 +37,9 @@ using media::MediaPlayerBridge;
using media::VideoFrame;
using webkit_media::WebVideoFrameImpl;
+// TODO(qinmin): Figure out where we should define this more appropriately
+static const uint32 kGLTextureExternalOES = 0x8D65;
+
namespace webkit_media {
// Because we create the media player lazily on android, the duration of the
@@ -47,9 +54,13 @@ static const float kTemporaryDuration = 100.0f;
bool WebMediaPlayerAndroid::incognito_mode_ = false;
WebMediaPlayerAndroid::WebMediaPlayerAndroid(
+ WebKit::WebFrame* frame,
WebMediaPlayerClient* client,
- WebKit::WebCookieJar* cookie_jar)
- : client_(client),
+ WebKit::WebCookieJar* cookie_jar,
+ webkit_media::WebMediaPlayerManagerAndroid* manager,
+ webkit_media::StreamTextureFactory* factory)
+ : frame_(frame),
+ client_(client),
buffered_(1u),
video_frame_(new WebVideoFrameImpl(VideoFrame::CreateEmptyFrame())),
proxy_(new WebMediaPlayerProxyAndroid(base::MessageLoopProxy::current(),
@@ -62,16 +73,25 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
buffered_bytes_(0),
did_loading_progress_(false),
cookie_jar_(cookie_jar),
+ manager_(manager),
pending_play_event_(false),
network_state_(WebMediaPlayer::NetworkStateEmpty),
- ready_state_(WebMediaPlayer::ReadyStateHaveNothing) {
- video_frame_.reset(new WebVideoFrameImpl(VideoFrame::CreateEmptyFrame()));
+ ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
+ texture_id_(0),
+ stream_id_(0),
+ needs_establish_peer_(true),
+ stream_texture_factory_(factory) {
+ player_id_ = manager_->RegisterMediaPlayer(this);
+ if (stream_texture_factory_.get())
+ stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy());
}
WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
if (media_player_.get()) {
media_player_->Stop();
}
+
+ manager_->UnregisterMediaPlayer(player_id_);
}
void WebMediaPlayerAndroid::InitIncognito(bool incognito_mode) {
@@ -437,9 +457,20 @@ void WebMediaPlayerAndroid::UpdateReadyState(
client_->readyStateChanged();
}
-void WebMediaPlayerAndroid::SetVideoSurface(jobject j_surface) {
- if (media_player_.get())
- media_player_->SetVideoSurface(j_surface);
+void WebMediaPlayerAndroid::ReleaseMediaResources() {
+ // Pause the media player first.
+ pause();
+ client_->playbackStateChanged();
+
+ if (media_player_.get()) {
+ // Save the current media player status.
+ pending_seek_ = currentTime();
+ duration_ = duration();
+
+ media_player_.reset();
+ needs_establish_peer_ = true;
+ }
+ prepared_ = false;
}
void WebMediaPlayerAndroid::InitializeMediaPlayer() {
@@ -450,8 +481,8 @@ void WebMediaPlayerAndroid::InitializeMediaPlayer() {
std::string cookies;
if (cookie_jar_ != NULL) {
- WebURL url(url_);
- cookies = UTF16ToUTF8(cookie_jar_->cookies(url, url));
+ WebURL first_party_url(frame_->document().firstPartyForCookies());
+ cookies = UTF16ToUTF8(cookie_jar_->cookies(url_, first_party_url));
}
media_player_->SetDataSource(url_.spec(), cookies, incognito_mode_);
@@ -466,6 +497,16 @@ void WebMediaPlayerAndroid::InitializeMediaPlayer() {
void WebMediaPlayerAndroid::PlayInternal() {
CHECK(prepared_);
+ if (hasVideo() && stream_texture_factory_.get()) {
+ if (!stream_id_)
+ CreateStreamTexture();
+
+ if (needs_establish_peer_) {
+ stream_texture_factory_->EstablishPeer(stream_id_, player_id_);
+ needs_establish_peer_ = false;
+ }
+ }
+
if (paused())
media_player_->Start(base::Bind(
&WebMediaPlayerProxyAndroid::PlaybackCompleteCallback, proxy_));
@@ -483,7 +524,36 @@ void WebMediaPlayerAndroid::SeekInternal(float seconds) {
&WebMediaPlayerProxyAndroid::SeekCompleteCallback, proxy_));
}
+void WebMediaPlayerAndroid::CreateStreamTexture() {
+ DCHECK(!stream_id_);
+ DCHECK(!texture_id_);
+ stream_id_ = stream_texture_factory_->CreateStreamTexture(&texture_id_);
+ if (texture_id_)
+ video_frame_.reset(new WebVideoFrameImpl(VideoFrame::WrapNativeTexture(
+ texture_id_,
+ kGLTextureExternalOES,
+ texture_size_.width,
+ texture_size_.height,
+ base::TimeDelta(),
+ base::TimeDelta(),
+ base::Bind(&WebMediaPlayerAndroid::DestroyStreamTexture,
+ base::Unretained(this)))));
+}
+
+void WebMediaPlayerAndroid::DestroyStreamTexture() {
+ DCHECK(stream_id_);
+ DCHECK(texture_id_);
+ stream_texture_factory_->DestroyStreamTexture(texture_id_);
+ texture_id_ = 0;
+ stream_id_ = 0;
+}
+
WebVideoFrame* WebMediaPlayerAndroid::getCurrentFrame() {
+ if (!stream_texture_proxy_->IsInitialized() && stream_id_) {
+ stream_texture_proxy_->Initialize(
+ stream_id_, video_frame_->width(), video_frame_->height());
+ }
+
return video_frame_.get();
}
@@ -491,4 +561,11 @@ void WebMediaPlayerAndroid::putCurrentFrame(
WebVideoFrame* web_video_frame) {
}
+// This gets called both on compositor and main thread.
+void WebMediaPlayerAndroid::setStreamTextureClient(
+ WebKit::WebStreamTextureClient* client) {
+ if (stream_texture_proxy_.get())
+ stream_texture_proxy_->SetClient(client);
+}
+
} // namespace webkit_media
diff --git a/webkit/media/android/webmediaplayer_android.h b/webkit/media/android/webmediaplayer_android.h
index c8935fa..b948d362 100644
--- a/webkit/media/android/webmediaplayer_android.h
+++ b/webkit/media/android/webmediaplayer_android.h
@@ -4,6 +4,7 @@
#ifndef WEBKIT_MEDIA_ANDROID_WEBMEDIAPLAYER_ANDROID_H_
#define WEBKIT_MEDIA_ANDROID_WEBMEDIAPLAYER_ANDROID_H_
+#pragma once
#include <jni.h>
@@ -18,6 +19,7 @@
namespace WebKit {
class WebCookieJar;
+class WebFrame;
}
namespace media {
@@ -26,6 +28,9 @@ class MediaPlayerBridge;
namespace webkit_media {
+class StreamTextureFactory;
+class StreamTextureProxy;
+class WebMediaPlayerManagerAndroid;
class WebMediaPlayerProxyAndroid;
// This class serves as the android implementation of WebKit::WebMediaPlayer.
@@ -35,8 +40,11 @@ class WebMediaPlayerAndroid :
public WebKit::WebMediaPlayer,
public base::SupportsWeakPtr<WebMediaPlayerAndroid> {
public:
- WebMediaPlayerAndroid(WebKit::WebMediaPlayerClient* client,
- WebKit::WebCookieJar* cookie_jar);
+ WebMediaPlayerAndroid(WebKit::WebFrame* frame,
+ WebKit::WebMediaPlayerClient* client,
+ WebKit::WebCookieJar* cookie_jar,
+ webkit_media::WebMediaPlayerManagerAndroid* manager,
+ webkit_media::StreamTextureFactory* factory);
virtual ~WebMediaPlayerAndroid();
// Set |incognito_mode_| to true if in incognito mode.
@@ -105,6 +113,8 @@ class WebMediaPlayerAndroid :
// compositor thread.
virtual WebKit::WebVideoFrame* getCurrentFrame();
virtual void putCurrentFrame(WebKit::WebVideoFrame*);
+ virtual void setStreamTextureClient(
+ WebKit::WebStreamTextureClient* client);
// Media player callback handlers.
void OnMediaPrepared();
@@ -115,8 +125,10 @@ class WebMediaPlayerAndroid :
void OnMediaInfo(int info_type);
void OnVideoSizeChanged(int width, int height);
- // Method to set the video surface for android media player.
- void SetVideoSurface(jobject j_surface);
+ // This function is called by WebMediaPlayerManagerAndroid to pause the video
+ // and release |media_player_| and its surface texture when we switch tabs.
+ // However, the actual GlTexture is not released to keep the video screenshot.
+ void ReleaseMediaResources();
private:
// Create a media player to load the |url_| and prepare for playback.
@@ -134,9 +146,15 @@ class WebMediaPlayerAndroid :
void UpdateNetworkState(WebKit::WebMediaPlayer::NetworkState state);
void UpdateReadyState(WebKit::WebMediaPlayer::ReadyState state);
+ // Methods for creation and deletion of stream texture.
+ void CreateStreamTexture();
+ void DestroyStreamTexture();
+
// whether the current process is incognito mode
static bool incognito_mode_;
+ WebKit::WebFrame* frame_;
+
WebKit::WebMediaPlayerClient* const client_;
// Save the list of buffered time ranges.
@@ -188,6 +206,12 @@ class WebMediaPlayerAndroid :
// Pointer to the cookie jar to get the cookie for the media url.
WebKit::WebCookieJar* cookie_jar_;
+ // Manager for managing this media player.
+ webkit_media::WebMediaPlayerManagerAndroid* manager_;
+
+ // Player ID assigned by the media player manager.
+ int player_id_;
+
// Whether the user has clicked the play button while media player
// is preparing.
bool pending_play_event_;
@@ -196,6 +220,22 @@ class WebMediaPlayerAndroid :
WebKit::WebMediaPlayer::NetworkState network_state_;
WebKit::WebMediaPlayer::ReadyState ready_state_;
+ // GL texture ID allocated to the video.
+ unsigned int texture_id_;
+
+ // Stream texture ID allocated to the video.
+ unsigned int stream_id_;
+
+ // Whether |media_player_| needs to re-establish the surface texture peer.
+ bool needs_establish_peer_;
+
+ // Object for allocating stream textures.
+ scoped_ptr<webkit_media::StreamTextureFactory> stream_texture_factory_;
+
+ // Object for calling back the compositor thread to repaint the video when a
+ // frame available. It should be initialized on the compositor thread.
+ scoped_ptr<webkit_media::StreamTextureProxy> stream_texture_proxy_;
+
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerAndroid);
};
diff --git a/webkit/media/android/webmediaplayer_manager_android.cc b/webkit/media/android/webmediaplayer_manager_android.cc
new file mode 100644
index 0000000..93c9733
--- /dev/null
+++ b/webkit/media/android/webmediaplayer_manager_android.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 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 "webkit/media/android/webmediaplayer_manager_android.h"
+
+#include "webkit/media/android/webmediaplayer_android.h"
+
+namespace webkit_media {
+
+WebMediaPlayerManagerAndroid::WebMediaPlayerManagerAndroid()
+ : next_media_player_id_(0) {
+}
+
+WebMediaPlayerManagerAndroid::~WebMediaPlayerManagerAndroid() {}
+
+int WebMediaPlayerManagerAndroid::RegisterMediaPlayer(
+ WebMediaPlayerAndroid* player) {
+ MediaPlayerInfo info;
+ info.player = player;
+ media_players_[next_media_player_id_] = info;
+ return next_media_player_id_++;
+}
+
+void WebMediaPlayerManagerAndroid::UnregisterMediaPlayer(int player_id) {
+ std::map<int32, MediaPlayerInfo>::iterator iter =
+ media_players_.find(player_id);
+ DCHECK(iter != media_players_.end());
+
+ media_players_.erase(player_id);
+}
+
+void WebMediaPlayerManagerAndroid::ReleaseMediaResources() {
+ std::map<int32, MediaPlayerInfo>::iterator player_it;
+ for (player_it = media_players_.begin();
+ player_it != media_players_.end(); ++player_it) {
+ (player_it->second).player->ReleaseMediaResources();
+ }
+}
+
+WebMediaPlayerAndroid* WebMediaPlayerManagerAndroid::GetMediaPlayer(
+ int player_id) {
+ std::map<int32, MediaPlayerInfo>::iterator iter =
+ media_players_.find(player_id);
+ if (iter != media_players_.end())
+ return (iter->second).player;
+ return NULL;
+}
+
+} // namespace webkit_media
diff --git a/webkit/media/android/webmediaplayer_manager_android.h b/webkit/media/android/webmediaplayer_manager_android.h
new file mode 100644
index 0000000..e8a046a
--- /dev/null
+++ b/webkit/media/android/webmediaplayer_manager_android.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 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 WEBKIT_MEDIA_ANDROID_WEBMEDIAPLAYER_MANAGER_ANDROID_H_
+#define WEBKIT_MEDIA_ANDROID_WEBMEDIAPLAYER_MANAGER_ANDROID_H_
+#pragma once
+
+#include <jni.h>
+#include <map>
+
+#include "base/basictypes.h"
+
+namespace webkit_media {
+
+class WebMediaPlayerAndroid;
+
+// Class for managing all the WebMediaPlayerAndroid objects in a renderer
+// process.
+class WebMediaPlayerManagerAndroid {
+ public:
+ WebMediaPlayerManagerAndroid();
+ ~WebMediaPlayerManagerAndroid();
+
+ // Register and unregister a WebMediaPlayerAndroid object.
+ int RegisterMediaPlayer(WebMediaPlayerAndroid* player);
+ void UnregisterMediaPlayer(int player_id);
+
+ // Release all the media resources on the renderer process.
+ void ReleaseMediaResources();
+
+ // Get the pointer to WebMediaPlayerAndroid given the |player_id|.
+ WebMediaPlayerAndroid* GetMediaPlayer(int player_id);
+
+ private:
+ // Information needed to manage WebMediaPlayerAndroid.
+ // TODO(qinmin): more informations will be added here for resource management.
+ struct MediaPlayerInfo {
+ webkit_media::WebMediaPlayerAndroid* player;
+ };
+
+ // Info for all available WebMediaPlayerAndroid on a page; kept so that
+ // we can enumerate them to send updates about tab focus and visibily.
+ std::map<int32, MediaPlayerInfo> media_players_;
+
+ int32 next_media_player_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerManagerAndroid);
+};
+
+} // namespace webkit_media
+
+#endif // WEBKIT_MEDIA_ANDROID_WEBMEDIAPLAYER_MANAGER_ANDROID_H_
diff --git a/webkit/media/webkit_media.gypi b/webkit/media/webkit_media.gypi
index ad6c642..111b5ef 100644
--- a/webkit/media/webkit_media.gypi
+++ b/webkit/media/webkit_media.gypi
@@ -15,8 +15,11 @@
],
'sources': [
'android/audio_decoder_android.cc',
+ 'android/stream_texture_factory_android.h',
'android/webmediaplayer_android.cc',
'android/webmediaplayer_android.h',
+ 'android/webmediaplayer_manager_android.cc',
+ 'android/webmediaplayer_manager_android.h',
'android/webmediaplayer_proxy_android.cc',
'android/webmediaplayer_proxy_android.h',
'active_loader.cc',