diff options
author | qinmin@chromium.org <qinmin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 21:40:28 +0000 |
---|---|---|
committer | qinmin@chromium.org <qinmin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-08 21:40:28 +0000 |
commit | cc012ea924a4ee7c83ec719755df97246709b279 (patch) | |
tree | 32d1da82be25b31cbb0150461c0ded3245af3bf4 /webkit/media | |
parent | e6be3247dacf7b371555695c318a14f9b884d581 (diff) | |
download | chromium_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.cc | 27 | ||||
-rw-r--r-- | webkit/media/android/webmediaplayer_android.h | 12 | ||||
-rw-r--r-- | webkit/media/android/webmediaplayer_manager_android.cc | 56 | ||||
-rw-r--r-- | webkit/media/android/webmediaplayer_manager_android.h | 16 |
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_; |