Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: content/renderer/media/android/webmediaplayer_android.cc

Issue 532993002: work-in-progress patch to fix context lost black video (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: no block Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/renderer/media/android/webmediaplayer_android.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/renderer/media/android/webmediaplayer_android.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698