OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/renderer/media/android/webmediaplayer_android.h" | 5 #include "content/renderer/media/android/webmediaplayer_android.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 media_task_runner_(task_runner), | 126 media_task_runner_(task_runner), |
127 ignore_metadata_duration_change_(false), | 127 ignore_metadata_duration_change_(false), |
128 pending_seek_(false), | 128 pending_seek_(false), |
129 seeking_(false), | 129 seeking_(false), |
130 did_loading_progress_(false), | 130 did_loading_progress_(false), |
131 player_manager_(player_manager), | 131 player_manager_(player_manager), |
132 cdm_manager_(cdm_manager), | 132 cdm_manager_(cdm_manager), |
133 network_state_(WebMediaPlayer::NetworkStateEmpty), | 133 network_state_(WebMediaPlayer::NetworkStateEmpty), |
134 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), | 134 ready_state_(WebMediaPlayer::ReadyStateHaveNothing), |
135 texture_id_(0), | 135 texture_id_(0), |
136 stream_id_(0), | |
137 is_playing_(false), | 136 is_playing_(false), |
138 needs_establish_peer_(true), | 137 needs_establish_peer_(true), |
139 stream_texture_proxy_initialized_(false), | |
140 has_size_info_(false), | 138 has_size_info_(false), |
141 stream_texture_factory_(factory), | 139 stream_texture_factory_(factory), |
142 needs_external_surface_(false), | 140 needs_external_surface_(false), |
143 has_valid_metadata_(false), | 141 has_valid_metadata_(false), |
144 video_frame_provider_client_(NULL), | 142 video_frame_provider_client_(NULL), |
143 stream_id_(0), | |
145 pending_playback_(false), | 144 pending_playback_(false), |
146 player_type_(MEDIA_PLAYER_TYPE_URL), | 145 player_type_(MEDIA_PLAYER_TYPE_URL), |
147 is_remote_(false), | 146 is_remote_(false), |
148 media_log_(media_log), | 147 media_log_(media_log), |
149 web_cdm_(NULL), | 148 web_cdm_(NULL), |
150 allow_stored_credentials_(false), | 149 allow_stored_credentials_(false), |
151 is_local_resource_(false), | 150 is_local_resource_(false), |
152 interpolator_(&default_tick_clock_), | 151 interpolator_(&default_tick_clock_), |
153 weak_factory_(this) { | 152 weak_factory_(this) { |
154 DCHECK(player_manager_); | 153 DCHECK(player_manager_); |
155 DCHECK(cdm_manager_); | 154 DCHECK(cdm_manager_); |
156 | 155 |
157 DCHECK(main_thread_checker_.CalledOnValidThread()); | 156 DCHECK(main_thread_checker_.CalledOnValidThread()); |
157 stream_texture_factory_->AddObserver(this); | |
158 | 158 |
159 player_id_ = player_manager_->RegisterMediaPlayer(this); | 159 player_id_ = player_manager_->RegisterMediaPlayer(this); |
160 | 160 |
161 #if defined(VIDEO_HOLE) | 161 #if defined(VIDEO_HOLE) |
162 force_use_overlay_embedded_video_ = CommandLine::ForCurrentProcess()-> | 162 force_use_overlay_embedded_video_ = CommandLine::ForCurrentProcess()-> |
163 HasSwitch(switches::kForceUseOverlayEmbeddedVideo); | 163 HasSwitch(switches::kForceUseOverlayEmbeddedVideo); |
164 if (force_use_overlay_embedded_video_ || | 164 if (force_use_overlay_embedded_video_ || |
165 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) { | 165 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) { |
166 // Defer stream texture creation until we are sure it's necessary. | 166 // Defer stream texture creation until we are sure it's necessary. |
167 needs_establish_peer_ = false; | 167 needs_establish_peer_ = false; |
168 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); | 168 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); |
169 } | 169 } |
170 #endif // defined(VIDEO_HOLE) | 170 #endif // defined(VIDEO_HOLE) |
171 TryCreateStreamTextureProxyIfNeeded(); | 171 TryCreateStreamTextureProxyIfNeeded(); |
172 interpolator_.SetUpperBound(base::TimeDelta()); | 172 interpolator_.SetUpperBound(base::TimeDelta()); |
173 } | 173 } |
174 | 174 |
175 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { | 175 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { |
176 DCHECK(main_thread_checker_.CalledOnValidThread()); | 176 DCHECK(main_thread_checker_.CalledOnValidThread()); |
177 SetVideoFrameProviderClient(NULL); | 177 SetVideoFrameProviderClient(NULL); |
178 client_->setWebLayer(NULL); | 178 client_->setWebLayer(NULL); |
179 | 179 |
180 if (player_manager_) { | 180 if (player_manager_) { |
181 player_manager_->DestroyPlayer(player_id_); | 181 player_manager_->DestroyPlayer(player_id_); |
182 player_manager_->UnregisterMediaPlayer(player_id_); | 182 player_manager_->UnregisterMediaPlayer(player_id_); |
183 } | 183 } |
184 | 184 |
185 if (stream_id_) { | 185 { |
186 GLES2Interface* gl = stream_texture_factory_->ContextGL(); | 186 base::AutoLock lock(client_lock_); |
187 gl->DeleteTextures(1, &texture_id_); | 187 if (stream_id_) { |
188 texture_id_ = 0; | 188 GLES2Interface* gl = stream_texture_factory_->ContextGL(); |
189 texture_mailbox_ = gpu::Mailbox(); | 189 gl->DeleteTextures(1, &texture_id_); |
190 stream_id_ = 0; | 190 texture_id_ = 0; |
191 texture_mailbox_ = gpu::Mailbox(); | |
192 stream_id_ = 0; | |
193 } | |
191 } | 194 } |
192 | 195 |
193 { | 196 { |
194 base::AutoLock auto_lock(current_frame_lock_); | 197 base::AutoLock auto_lock(current_frame_lock_); |
195 current_frame_ = NULL; | 198 current_frame_ = NULL; |
196 } | 199 } |
197 | 200 |
198 if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE && delegate_) | 201 if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE && delegate_) |
199 delegate_->PlayerGone(this); | 202 delegate_->PlayerGone(this); |
203 | |
204 stream_texture_factory_->RemoveObserver(this); | |
200 } | 205 } |
201 | 206 |
202 void WebMediaPlayerAndroid::load(LoadType load_type, | 207 void WebMediaPlayerAndroid::load(LoadType load_type, |
203 const blink::WebURL& url, | 208 const blink::WebURL& url, |
204 CORSMode cors_mode) { | 209 CORSMode cors_mode) { |
205 DCHECK(main_thread_checker_.CalledOnValidThread()); | 210 DCHECK(main_thread_checker_.CalledOnValidThread()); |
206 media::ReportMediaSchemeUma(GURL(url)); | 211 media::ReportMediaSchemeUma(GURL(url)); |
207 | 212 |
208 switch (load_type) { | 213 switch (load_type) { |
209 case LoadTypeURL: | 214 case LoadTypeURL: |
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
825 | 830 |
826 #if defined(VIDEO_HOLE) | 831 #if defined(VIDEO_HOLE) |
827 // Use H/W surface for encrypted video. | 832 // Use H/W surface for encrypted video. |
828 // TODO(qinmin): Change this so that only EME needs the H/W surface | 833 // TODO(qinmin): Change this so that only EME needs the H/W surface |
829 if (force_use_overlay_embedded_video_ || | 834 if (force_use_overlay_embedded_video_ || |
830 (media_source_delegate_ && media_source_delegate_->IsVideoEncrypted() && | 835 (media_source_delegate_ && media_source_delegate_->IsVideoEncrypted() && |
831 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo())) { | 836 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo())) { |
832 needs_external_surface_ = true; | 837 needs_external_surface_ = true; |
833 if (!paused() && !player_manager_->IsInFullscreen(frame_)) | 838 if (!paused() && !player_manager_->IsInFullscreen(frame_)) |
834 player_manager_->RequestExternalSurface(player_id_, last_computed_rect_); | 839 player_manager_->RequestExternalSurface(player_id_, last_computed_rect_); |
835 } else if (stream_texture_proxy_ && !stream_id_) { | 840 } else { |
836 // Do deferred stream texture creation finally. | 841 bool has_proxy = false; |
837 DoCreateStreamTexture(); | 842 bool has_stream_id = false; |
838 SetNeedsEstablishPeer(true); | 843 { |
844 base::AutoLock lock(client_lock_); | |
845 has_proxy = !!stream_texture_proxy_.get(); | |
846 has_stream_id = !!stream_id_; | |
847 } | |
848 if (has_proxy && !has_stream_id) { | |
849 // Do deferred stream texture creation finally. | |
850 DoCreateStreamTexture(); | |
851 SetNeedsEstablishPeer(true); | |
852 } | |
839 } | 853 } |
840 #endif // defined(VIDEO_HOLE) | 854 #endif // defined(VIDEO_HOLE) |
841 natural_size_.width = width; | 855 natural_size_.width = width; |
842 natural_size_.height = height; | 856 natural_size_.height = height; |
843 | 857 |
844 // When play() gets called, |natural_size_| may still be empty and | 858 // When play() gets called, |natural_size_| may still be empty and |
845 // EstablishSurfaceTexturePeer() will not get called. As a result, the video | 859 // EstablishSurfaceTexturePeer() will not get called. As a result, the video |
846 // may play without a surface texture. When we finally get the valid video | 860 // may play without a surface texture. When we finally get the valid video |
847 // size here, we should call EstablishSurfaceTexturePeer() if it has not been | 861 // size here, we should call EstablishSurfaceTexturePeer() if it has not been |
848 // previously called. | 862 // previously called. |
849 if (!paused() && needs_establish_peer_) | 863 if (!paused() && needs_establish_peer_) |
850 EstablishSurfaceTexturePeer(); | 864 EstablishSurfaceTexturePeer(); |
851 | 865 |
852 ReallocateVideoFrame(); | 866 ReallocateVideoFrame(); |
853 | 867 |
854 // For hidden video element (with style "display:none"), ensure the texture | 868 // For hidden video element (with style "display:none"), ensure the texture |
855 // size is set. | 869 // size is set. |
856 if (!is_remote_ && cached_stream_texture_size_ != natural_size_) { | 870 if (!is_remote_ && cached_stream_texture_size_ != natural_size_) { |
857 stream_texture_factory_->SetStreamTextureSize( | 871 { |
858 stream_id_, gfx::Size(natural_size_.width, natural_size_.height)); | 872 base::AutoLock lock(client_lock_); |
873 stream_texture_factory_->SetStreamTextureSize( | |
874 stream_id_, gfx::Size(natural_size_.width, natural_size_.height)); | |
875 } | |
859 cached_stream_texture_size_ = natural_size_; | 876 cached_stream_texture_size_ = natural_size_; |
860 } | 877 } |
861 | 878 |
862 // Lazily allocate compositing layer. | 879 // Lazily allocate compositing layer. |
863 if (!video_weblayer_) { | 880 if (!video_weblayer_) { |
864 video_weblayer_.reset(new cc_blink::WebLayerImpl( | 881 video_weblayer_.reset(new cc_blink::WebLayerImpl( |
865 cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0))); | 882 cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0))); |
866 client_->setWebLayer(video_weblayer_.get()); | 883 client_->setWebLayer(video_weblayer_.get()); |
867 } | 884 } |
868 | 885 |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1203 gfx::Rect(natural_size_), | 1220 gfx::Rect(natural_size_), |
1204 natural_size_, | 1221 natural_size_, |
1205 base::TimeDelta(), | 1222 base::TimeDelta(), |
1206 VideoFrame::ReadPixelsCB()); | 1223 VideoFrame::ReadPixelsCB()); |
1207 SetCurrentFrameInternal(new_frame); | 1224 SetCurrentFrameInternal(new_frame); |
1208 } | 1225 } |
1209 } | 1226 } |
1210 | 1227 |
1211 void WebMediaPlayerAndroid::SetVideoFrameProviderClient( | 1228 void WebMediaPlayerAndroid::SetVideoFrameProviderClient( |
1212 cc::VideoFrameProvider::Client* client) { | 1229 cc::VideoFrameProvider::Client* client) { |
1213 // This is called from both the main renderer thread and the compositor | 1230 base::AutoLock lock(client_lock_); |
qinmin
2014/09/13 23:49:44
In video_frame_provider_client_impl.cc, it mention
boliu
2014/09/14 00:12:30
Daniel's pseudo code threw me off. Yeah I don't th
| |
1214 // thread (when the main thread is blocked). | 1231 if (video_frame_provider_client_ && video_frame_provider_client_ != client) |
1215 if (video_frame_provider_client_) | |
1216 video_frame_provider_client_->StopUsingProvider(); | 1232 video_frame_provider_client_->StopUsingProvider(); |
1217 video_frame_provider_client_ = client; | 1233 video_frame_provider_client_ = client; |
1218 | 1234 |
1219 // Set the callback target when a frame is produced. | 1235 // Set the callback target when a frame is produced. |
1220 if (stream_texture_proxy_) { | 1236 if (stream_texture_proxy_) { |
1221 stream_texture_proxy_->SetClient(client); | 1237 stream_texture_proxy_->Bind( |
1222 // If client exists, the compositor thread calls it. At that time, | 1238 stream_id_, client, base::MessageLoopProxy::current()); |
1223 // stream_id_, needs_external_surface_, is_remote_ can be accessed because | |
1224 // the main thread is blocked. | |
1225 if (client && !stream_texture_proxy_initialized_ && stream_id_ && | |
1226 !needs_external_surface_ && !is_remote_) { | |
1227 stream_texture_proxy_->BindToCurrentThread(stream_id_); | |
1228 stream_texture_proxy_initialized_ = true; | |
1229 } | |
1230 } | 1239 } |
1231 } | 1240 } |
1232 | 1241 |
1233 void WebMediaPlayerAndroid::SetCurrentFrameInternal( | 1242 void WebMediaPlayerAndroid::SetCurrentFrameInternal( |
1234 scoped_refptr<media::VideoFrame>& video_frame) { | 1243 scoped_refptr<media::VideoFrame>& video_frame) { |
1235 DCHECK(main_thread_checker_.CalledOnValidThread()); | 1244 DCHECK(main_thread_checker_.CalledOnValidThread()); |
1236 base::AutoLock auto_lock(current_frame_lock_); | 1245 base::AutoLock auto_lock(current_frame_lock_); |
1237 current_frame_ = video_frame; | 1246 current_frame_ = video_frame; |
1238 } | 1247 } |
1239 | 1248 |
1240 scoped_refptr<media::VideoFrame> WebMediaPlayerAndroid::GetCurrentFrame() { | 1249 scoped_refptr<media::VideoFrame> WebMediaPlayerAndroid::GetCurrentFrame() { |
1241 scoped_refptr<VideoFrame> video_frame; | 1250 scoped_refptr<VideoFrame> video_frame; |
1242 { | 1251 { |
1243 base::AutoLock auto_lock(current_frame_lock_); | 1252 base::AutoLock auto_lock(current_frame_lock_); |
1244 video_frame = current_frame_; | 1253 video_frame = current_frame_; |
1245 } | 1254 } |
1246 | 1255 |
1247 return video_frame; | 1256 return video_frame; |
1248 } | 1257 } |
1249 | 1258 |
1250 void WebMediaPlayerAndroid::PutCurrentFrame( | 1259 void WebMediaPlayerAndroid::PutCurrentFrame( |
1251 const scoped_refptr<media::VideoFrame>& frame) { | 1260 const scoped_refptr<media::VideoFrame>& frame) { |
1252 } | 1261 } |
1253 | 1262 |
1263 void WebMediaPlayerAndroid::ResetStreamTextureProxy() { | |
1264 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
1265 | |
1266 { | |
1267 base::AutoLock lock(client_lock_); | |
1268 if (stream_id_) { | |
1269 GLES2Interface* gl = stream_texture_factory_->ContextGL(); | |
1270 gl->DeleteTextures(1, &texture_id_); | |
1271 texture_id_ = 0; | |
1272 texture_mailbox_ = gpu::Mailbox(); | |
1273 stream_id_ = 0; | |
1274 } | |
1275 stream_texture_proxy_.reset(); | |
1276 } | |
1277 needs_establish_peer_ = !needs_external_surface_ && !is_remote_ && | |
1278 !player_manager_->IsInFullscreen(frame_) && | |
1279 (hasVideo() || IsHLSStream()); | |
1280 | |
1281 TryCreateStreamTextureProxyIfNeeded(); | |
1282 if (needs_establish_peer_ && is_playing_) | |
1283 EstablishSurfaceTexturePeer(); | |
1284 } | |
1285 | |
1254 void WebMediaPlayerAndroid::TryCreateStreamTextureProxyIfNeeded() { | 1286 void WebMediaPlayerAndroid::TryCreateStreamTextureProxyIfNeeded() { |
1255 DCHECK(main_thread_checker_.CalledOnValidThread()); | 1287 DCHECK(main_thread_checker_.CalledOnValidThread()); |
1256 // Already created. | 1288 { |
1257 if (stream_texture_proxy_) | 1289 // Already created. |
1258 return; | 1290 base::AutoLock lock(client_lock_); |
1291 if (stream_texture_proxy_) | |
1292 return; | |
1293 } | |
1259 | 1294 |
1260 // No factory to create proxy. | 1295 // No factory to create proxy. |
1261 if (!stream_texture_factory_) | 1296 if (!stream_texture_factory_) |
1262 return; | 1297 return; |
1263 | 1298 |
1299 base::AutoLock lock(client_lock_); | |
1264 stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy()); | 1300 stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy()); |
1265 if (needs_establish_peer_ && stream_texture_proxy_) { | 1301 if (needs_establish_peer_ && stream_texture_proxy_ && |
1266 DoCreateStreamTexture(); | 1302 video_frame_provider_client_) { |
1267 ReallocateVideoFrame(); | 1303 stream_texture_proxy_->Bind( |
1304 stream_id_, | |
1305 video_frame_provider_client_, | |
1306 RenderThreadImpl::current()->compositor_message_loop_proxy()); | |
1268 } | 1307 } |
1269 | |
1270 if (stream_texture_proxy_ && video_frame_provider_client_) | |
1271 stream_texture_proxy_->SetClient(video_frame_provider_client_); | |
1272 } | 1308 } |
1273 | 1309 |
1274 void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() { | 1310 void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() { |
1275 DCHECK(main_thread_checker_.CalledOnValidThread()); | 1311 DCHECK(main_thread_checker_.CalledOnValidThread()); |
1312 base::AutoLock lock(client_lock_); | |
1276 if (!stream_texture_proxy_) | 1313 if (!stream_texture_proxy_) |
1277 return; | 1314 return; |
1278 | 1315 |
1279 if (stream_texture_factory_.get() && stream_id_) | 1316 if (stream_texture_factory_.get() && stream_id_) |
1280 stream_texture_factory_->EstablishPeer(stream_id_, player_id_); | 1317 stream_texture_factory_->EstablishPeer(stream_id_, player_id_); |
1281 | 1318 |
1282 // Set the deferred size because the size was changed in remote mode. | 1319 // Set the deferred size because the size was changed in remote mode. |
1283 if (!is_remote_ && cached_stream_texture_size_ != natural_size_) { | 1320 if (!is_remote_ && cached_stream_texture_size_ != natural_size_) { |
1284 stream_texture_factory_->SetStreamTextureSize( | 1321 stream_texture_factory_->SetStreamTextureSize( |
1285 stream_id_, gfx::Size(natural_size_.width, natural_size_.height)); | 1322 stream_id_, gfx::Size(natural_size_.width, natural_size_.height)); |
1286 cached_stream_texture_size_ = natural_size_; | 1323 cached_stream_texture_size_ = natural_size_; |
1287 } | 1324 } |
1288 | 1325 |
1289 needs_establish_peer_ = false; | 1326 needs_establish_peer_ = false; |
1290 } | 1327 } |
1291 | 1328 |
1292 void WebMediaPlayerAndroid::DoCreateStreamTexture() { | 1329 void WebMediaPlayerAndroid::DoCreateStreamTexture() { |
1330 base::AutoLock lock(client_lock_); | |
1293 DCHECK(main_thread_checker_.CalledOnValidThread()); | 1331 DCHECK(main_thread_checker_.CalledOnValidThread()); |
1294 DCHECK(!stream_id_); | 1332 DCHECK(!stream_id_); |
1295 DCHECK(!texture_id_); | 1333 DCHECK(!texture_id_); |
1296 stream_id_ = stream_texture_factory_->CreateStreamTexture( | 1334 stream_id_ = stream_texture_factory_->CreateStreamTexture( |
1297 kGLTextureExternalOES, &texture_id_, &texture_mailbox_); | 1335 kGLTextureExternalOES, &texture_id_, &texture_mailbox_); |
1298 } | 1336 } |
1299 | 1337 |
1300 void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) { | 1338 void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) { |
1301 needs_establish_peer_ = needs_establish_peer; | 1339 needs_establish_peer_ = needs_establish_peer; |
1302 } | 1340 } |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1791 | 1829 |
1792 bool WebMediaPlayerAndroid::IsHLSStream() const { | 1830 bool WebMediaPlayerAndroid::IsHLSStream() const { |
1793 std::string mime; | 1831 std::string mime; |
1794 GURL url = redirected_url_.is_empty() ? url_ : redirected_url_; | 1832 GURL url = redirected_url_.is_empty() ? url_ : redirected_url_; |
1795 if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime)) | 1833 if (!net::GetMimeTypeFromFile(base::FilePath(url.path()), &mime)) |
1796 return false; | 1834 return false; |
1797 return !mime.compare("application/x-mpegurl"); | 1835 return !mime.compare("application/x-mpegurl"); |
1798 } | 1836 } |
1799 | 1837 |
1800 } // namespace content | 1838 } // namespace content |
OLD | NEW |