summaryrefslogtreecommitdiffstats
path: root/webkit/media
diff options
context:
space:
mode:
authorqinmin@chromium.org <qinmin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 21:40:28 +0000
committerqinmin@chromium.org <qinmin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-08 21:40:28 +0000
commitcc012ea924a4ee7c83ec719755df97246709b279 (patch)
tree32d1da82be25b31cbb0150461c0ded3245af3bf4 /webkit/media
parente6be3247dacf7b371555695c318a14f9b884d581 (diff)
downloadchromium_src-cc012ea924a4ee7c83ec719755df97246709b279.zip
chromium_src-cc012ea924a4ee7c83ec719755df97246709b279.tar.gz
chromium_src-cc012ea924a4ee7c83ec719755df97246709b279.tar.bz2
Adding the logic for releasing decoder resources in WebMediaPlayerManagerAndroid
This change adds the logic to release paused mediaplayers when another player requests for decoder. Also, it addresses a NPE problem that RenderViewImpl could go away before WebMediaPlayerAndroid when closing tabs BUG= TEST= Review URL: https://chromiumcodereview.appspot.com/10533049 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@141291 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/media')
-rw-r--r--webkit/media/android/webmediaplayer_android.cc27
-rw-r--r--webkit/media/android/webmediaplayer_android.h12
-rw-r--r--webkit/media/android/webmediaplayer_manager_android.cc56
-rw-r--r--webkit/media/android/webmediaplayer_manager_android.h16
4 files changed, 89 insertions, 22 deletions
diff --git a/webkit/media/android/webmediaplayer_android.cc b/webkit/media/android/webmediaplayer_android.cc
index 9ca732f..03abc610 100644
--- a/webkit/media/android/webmediaplayer_android.cc
+++ b/webkit/media/android/webmediaplayer_android.cc
@@ -63,7 +63,8 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
client_(client),
buffered_(1u),
video_frame_(new WebVideoFrameImpl(VideoFrame::CreateEmptyFrame())),
- proxy_(new WebMediaPlayerProxyAndroid(base::MessageLoopProxy::current(),
+ main_loop_(MessageLoop::current()),
+ proxy_(new WebMediaPlayerProxyAndroid(main_loop_->message_loop_proxy(),
AsWeakPtr())),
prepared_(false),
duration_(0),
@@ -81,17 +82,19 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
stream_id_(0),
needs_establish_peer_(true),
stream_texture_factory_(factory) {
- player_id_ = manager_->RegisterMediaPlayer(this);
+ main_loop_->AddDestructionObserver(this);
+ if (manager_)
+ 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();
- }
+ if (manager_)
+ manager_->UnregisterMediaPlayer(player_id_);
- manager_->UnregisterMediaPlayer(player_id_);
+ if (main_loop_)
+ main_loop_->RemoveDestructionObserver(this);
}
void WebMediaPlayerAndroid::InitIncognito(bool incognito_mode) {
@@ -484,6 +487,10 @@ void WebMediaPlayerAndroid::ReleaseMediaResources() {
prepared_ = false;
}
+bool WebMediaPlayerAndroid::IsInitialized() const {
+ return (media_player_ != NULL);
+}
+
void WebMediaPlayerAndroid::InitializeMediaPlayer() {
CHECK(!media_player_.get());
prepared_ = false;
@@ -497,6 +504,9 @@ void WebMediaPlayerAndroid::InitializeMediaPlayer() {
}
media_player_->SetDataSource(url_.spec(), cookies, incognito_mode_);
+ if (manager_)
+ manager_->RequestMediaResources(player_id_);
+
media_player_->Prepare(
base::Bind(&WebMediaPlayerProxyAndroid::MediaInfoCallback, proxy_),
base::Bind(&WebMediaPlayerProxyAndroid::MediaErrorCallback, proxy_),
@@ -559,6 +569,11 @@ void WebMediaPlayerAndroid::DestroyStreamTexture() {
stream_id_ = 0;
}
+void WebMediaPlayerAndroid::WillDestroyCurrentMessageLoop() {
+ manager_ = NULL;
+ main_loop_ = NULL;
+}
+
WebVideoFrame* WebMediaPlayerAndroid::getCurrentFrame() {
if (!stream_texture_proxy_->IsInitialized() && stream_id_) {
stream_texture_proxy_->Initialize(
diff --git a/webkit/media/android/webmediaplayer_android.h b/webkit/media/android/webmediaplayer_android.h
index 28fd84e..97de531 100644
--- a/webkit/media/android/webmediaplayer_android.h
+++ b/webkit/media/android/webmediaplayer_android.h
@@ -9,7 +9,7 @@
#include <jni.h>
#include "base/basictypes.h"
-#include "base/message_loop_proxy.h"
+#include "base/message_loop.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaPlayer.h"
@@ -38,6 +38,7 @@ class WebMediaPlayerProxyAndroid;
// media player, and reports player state changes to the webkit.
class WebMediaPlayerAndroid :
public WebKit::WebMediaPlayer,
+ public MessageLoop::DestructionObserver,
public base::SupportsWeakPtr<WebMediaPlayerAndroid> {
public:
WebMediaPlayerAndroid(WebKit::WebFrame* frame,
@@ -134,6 +135,12 @@ class WebMediaPlayerAndroid :
// However, the actual GlTexture is not released to keep the video screenshot.
void ReleaseMediaResources();
+ // Whether |media_player_| has been initialized.
+ bool IsInitialized() const;
+
+ // Method inherited from DestructionObserver.
+ virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
+
private:
// Create a media player to load the |url_| and prepare for playback.
// Because of limited decoding resources on mobile devices, idle media players
@@ -176,6 +183,9 @@ class WebMediaPlayerAndroid :
// The video frame object used for renderering by WebKit.
scoped_ptr<WebKit::WebVideoFrame> video_frame_;
+ // Message loops for main renderer thread.
+ MessageLoop* main_loop_;
+
// Proxy object that delegates method calls on Render Thread.
// This object is created on the Render Thread and is only called in the
// destructor.
diff --git a/webkit/media/android/webmediaplayer_manager_android.cc b/webkit/media/android/webmediaplayer_manager_android.cc
index 93c9733..4d2ae88 100644
--- a/webkit/media/android/webmediaplayer_manager_android.cc
+++ b/webkit/media/android/webmediaplayer_manager_android.cc
@@ -6,44 +6,82 @@
#include "webkit/media/android/webmediaplayer_android.h"
+// Threshold on the number of media players per renderer before we start
+// attempting to release inactive media players.
+static const int kMediaPlayerThreshold = 2;
+
namespace webkit_media {
WebMediaPlayerManagerAndroid::WebMediaPlayerManagerAndroid()
: next_media_player_id_(0) {
}
-WebMediaPlayerManagerAndroid::~WebMediaPlayerManagerAndroid() {}
+WebMediaPlayerManagerAndroid::~WebMediaPlayerManagerAndroid() {
+ ReleaseMediaResources();
+}
int WebMediaPlayerManagerAndroid::RegisterMediaPlayer(
WebMediaPlayerAndroid* player) {
- MediaPlayerInfo info;
- info.player = player;
- media_players_[next_media_player_id_] = info;
+ media_players_[next_media_player_id_] = player;
return next_media_player_id_++;
}
void WebMediaPlayerManagerAndroid::UnregisterMediaPlayer(int player_id) {
- std::map<int32, MediaPlayerInfo>::iterator iter =
+ std::map<int32, WebMediaPlayerAndroid*>::iterator iter =
media_players_.find(player_id);
DCHECK(iter != media_players_.end());
media_players_.erase(player_id);
}
+void WebMediaPlayerManagerAndroid::RequestMediaResources(int player_id) {
+ std::map<int32, WebMediaPlayerAndroid*>::iterator iter =
+ media_players_.find(player_id);
+ DCHECK(iter != media_players_.end());
+
+ if ((iter->second)->IsInitialized())
+ return;
+
+ // Release active players that are paused. Because we only release paused
+ // players, the number of running players could go beyond the limit.
+ // TODO(qinmin): we should use LRU to release the oldest player if we are
+ // reaching hardware limit.
+ if (GetActivePlayerCount() < kMediaPlayerThreshold)
+ return;
+
+ std::map<int32, WebMediaPlayerAndroid*>::iterator player_it;
+ for (player_it = media_players_.begin();
+ player_it != media_players_.end(); ++player_it) {
+ WebMediaPlayerAndroid* player = player_it->second;
+ if (player->IsInitialized() && player->paused())
+ player->ReleaseMediaResources();
+ }
+}
+
void WebMediaPlayerManagerAndroid::ReleaseMediaResources() {
- std::map<int32, MediaPlayerInfo>::iterator player_it;
+ std::map<int32, WebMediaPlayerAndroid*>::iterator player_it;
for (player_it = media_players_.begin();
player_it != media_players_.end(); ++player_it) {
- (player_it->second).player->ReleaseMediaResources();
+ (player_it->second)->ReleaseMediaResources();
+ }
+}
+
+int32 WebMediaPlayerManagerAndroid::GetActivePlayerCount() {
+ int32 count = 0;
+ std::map<int32, WebMediaPlayerAndroid*>::iterator iter;
+ for (iter = media_players_.begin(); iter != media_players_.end(); ++iter) {
+ if ((iter->second)->IsInitialized())
+ count++;
}
+ return count;
}
WebMediaPlayerAndroid* WebMediaPlayerManagerAndroid::GetMediaPlayer(
int player_id) {
- std::map<int32, MediaPlayerInfo>::iterator iter =
+ std::map<int32, WebMediaPlayerAndroid*>::iterator iter =
media_players_.find(player_id);
if (iter != media_players_.end())
- return (iter->second).player;
+ return iter->second;
return NULL;
}
diff --git a/webkit/media/android/webmediaplayer_manager_android.h b/webkit/media/android/webmediaplayer_manager_android.h
index e8a046a..49ca4c3 100644
--- a/webkit/media/android/webmediaplayer_manager_android.h
+++ b/webkit/media/android/webmediaplayer_manager_android.h
@@ -26,6 +26,13 @@ class WebMediaPlayerManagerAndroid {
int RegisterMediaPlayer(WebMediaPlayerAndroid* player);
void UnregisterMediaPlayer(int player_id);
+ // Called when a mediaplayer starts to decode media. If the number
+ // of active decoders hits the limit, release some resources.
+ // TODO(qinmin): we need to classify between video and audio decoders.
+ // Audio decoders are inexpensive. And css animations often come with
+ // lots of small audio files.
+ void RequestMediaResources(int player_id);
+
// Release all the media resources on the renderer process.
void ReleaseMediaResources();
@@ -33,15 +40,12 @@ class WebMediaPlayerManagerAndroid {
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;
- };
+ // Get the number of active players.
+ int32 GetActivePlayerCount();
// 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_;
+ std::map<int32, WebMediaPlayerAndroid*> media_players_;
int32 next_media_player_id_;