Chromium Code Reviews| 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/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 153 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) { | 153 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) { |
| 154 // Defer stream texture creation until we are sure it's necessary. | 154 // Defer stream texture creation until we are sure it's necessary. |
| 155 needs_establish_peer_ = false; | 155 needs_establish_peer_ = false; |
| 156 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); | 156 current_frame_ = VideoFrame::CreateBlackFrame(gfx::Size(1, 1)); |
| 157 } | 157 } |
| 158 #endif // defined(VIDEO_HOLE) | 158 #endif // defined(VIDEO_HOLE) |
| 159 TryCreateStreamTextureProxyIfNeeded(); | 159 TryCreateStreamTextureProxyIfNeeded(); |
| 160 } | 160 } |
| 161 | 161 |
| 162 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { | 162 WebMediaPlayerAndroid::~WebMediaPlayerAndroid() { |
| 163 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 163 SetVideoFrameProviderClient(NULL); | 164 SetVideoFrameProviderClient(NULL); |
| 164 client_->setWebLayer(NULL); | 165 client_->setWebLayer(NULL); |
| 165 | 166 |
| 166 if (player_manager_) { | 167 if (player_manager_) { |
| 167 player_manager_->DestroyPlayer(player_id_); | 168 player_manager_->DestroyPlayer(player_id_); |
| 168 player_manager_->UnregisterMediaPlayer(player_id_); | 169 player_manager_->UnregisterMediaPlayer(player_id_); |
| 169 } | 170 } |
| 170 | 171 |
| 171 if (stream_id_) { | 172 if (stream_id_) { |
| 172 GLES2Interface* gl = stream_texture_factory_->ContextGL(); | 173 GLES2Interface* gl = stream_texture_factory_->ContextGL(); |
| 173 gl->DeleteTextures(1, &texture_id_); | 174 gl->DeleteTextures(1, &texture_id_); |
| 174 texture_id_ = 0; | 175 texture_id_ = 0; |
| 175 texture_mailbox_ = gpu::Mailbox(); | 176 texture_mailbox_ = gpu::Mailbox(); |
| 176 stream_id_ = 0; | 177 stream_id_ = 0; |
| 177 } | 178 } |
| 178 | 179 |
| 179 { | 180 { |
| 180 base::AutoLock auto_lock(current_frame_lock_); | 181 base::AutoLock auto_lock(current_frame_lock_); |
| 181 current_frame_ = NULL; | 182 current_frame_ = NULL; |
| 182 } | 183 } |
| 183 | 184 |
| 184 if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE && delegate_) | 185 if (player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE && delegate_) |
| 185 delegate_->PlayerGone(this); | 186 delegate_->PlayerGone(this); |
| 186 } | 187 } |
| 187 | 188 |
| 188 void WebMediaPlayerAndroid::load(LoadType load_type, | 189 void WebMediaPlayerAndroid::load(LoadType load_type, |
| 189 const blink::WebURL& url, | 190 const blink::WebURL& url, |
| 190 CORSMode cors_mode) { | 191 CORSMode cors_mode) { |
| 192 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 191 ReportMediaSchemeUma(GURL(url)); | 193 ReportMediaSchemeUma(GURL(url)); |
| 192 | 194 |
| 193 switch (load_type) { | 195 switch (load_type) { |
| 194 case LoadTypeURL: | 196 case LoadTypeURL: |
| 195 player_type_ = MEDIA_PLAYER_TYPE_URL; | 197 player_type_ = MEDIA_PLAYER_TYPE_URL; |
| 196 break; | 198 break; |
| 197 | 199 |
| 198 case LoadTypeMediaSource: | 200 case LoadTypeMediaSource: |
| 199 player_type_ = MEDIA_PLAYER_TYPE_MEDIA_SOURCE; | 201 player_type_ = MEDIA_PLAYER_TYPE_MEDIA_SOURCE; |
| 200 break; | 202 break; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 249 } | 251 } |
| 250 | 252 |
| 251 if (player_manager_->ShouldEnterFullscreen(frame_)) | 253 if (player_manager_->ShouldEnterFullscreen(frame_)) |
| 252 player_manager_->EnterFullscreen(player_id_, frame_); | 254 player_manager_->EnterFullscreen(player_id_, frame_); |
| 253 | 255 |
| 254 UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); | 256 UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); |
| 255 UpdateReadyState(WebMediaPlayer::ReadyStateHaveNothing); | 257 UpdateReadyState(WebMediaPlayer::ReadyStateHaveNothing); |
| 256 } | 258 } |
| 257 | 259 |
| 258 void WebMediaPlayerAndroid::DidLoadMediaInfo(MediaInfoLoader::Status status) { | 260 void WebMediaPlayerAndroid::DidLoadMediaInfo(MediaInfoLoader::Status status) { |
| 261 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 259 DCHECK(!media_source_delegate_); | 262 DCHECK(!media_source_delegate_); |
| 260 if (status == MediaInfoLoader::kFailed) { | 263 if (status == MediaInfoLoader::kFailed) { |
| 261 info_loader_.reset(); | 264 info_loader_.reset(); |
| 262 UpdateNetworkState(WebMediaPlayer::NetworkStateNetworkError); | 265 UpdateNetworkState(WebMediaPlayer::NetworkStateNetworkError); |
| 263 return; | 266 return; |
| 264 } | 267 } |
| 265 | 268 |
| 266 InitializePlayer(0); | 269 InitializePlayer(0); |
| 267 | 270 |
| 268 UpdateNetworkState(WebMediaPlayer::NetworkStateIdle); | 271 UpdateNetworkState(WebMediaPlayer::NetworkStateIdle); |
| 269 } | 272 } |
| 270 | 273 |
| 271 void WebMediaPlayerAndroid::play() { | 274 void WebMediaPlayerAndroid::play() { |
| 275 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 272 #if defined(VIDEO_HOLE) | 276 #if defined(VIDEO_HOLE) |
| 273 if (hasVideo() && needs_external_surface_ && | 277 if (hasVideo() && needs_external_surface_ && |
| 274 !player_manager_->IsInFullscreen(frame_)) { | 278 !player_manager_->IsInFullscreen(frame_)) { |
| 275 DCHECK(!needs_establish_peer_); | 279 DCHECK(!needs_establish_peer_); |
| 276 player_manager_->RequestExternalSurface(player_id_, last_computed_rect_); | 280 player_manager_->RequestExternalSurface(player_id_, last_computed_rect_); |
| 277 } | 281 } |
| 278 #endif // defined(VIDEO_HOLE) | 282 #endif // defined(VIDEO_HOLE) |
| 279 | 283 |
| 280 TryCreateStreamTextureProxyIfNeeded(); | 284 TryCreateStreamTextureProxyIfNeeded(); |
| 281 // There is no need to establish the surface texture peer for fullscreen | 285 // There is no need to establish the surface texture peer for fullscreen |
| 282 // video. | 286 // video. |
| 283 if (hasVideo() && needs_establish_peer_ && | 287 if (hasVideo() && needs_establish_peer_ && |
| 284 !player_manager_->IsInFullscreen(frame_)) { | 288 !player_manager_->IsInFullscreen(frame_)) { |
| 285 EstablishSurfaceTexturePeer(); | 289 EstablishSurfaceTexturePeer(); |
| 286 } | 290 } |
| 287 | 291 |
| 288 if (paused()) | 292 if (paused()) |
| 289 player_manager_->Start(player_id_); | 293 player_manager_->Start(player_id_); |
| 290 UpdatePlayingState(true); | 294 UpdatePlayingState(true); |
| 291 UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); | 295 UpdateNetworkState(WebMediaPlayer::NetworkStateLoading); |
| 292 } | 296 } |
| 293 | 297 |
| 294 void WebMediaPlayerAndroid::pause() { | 298 void WebMediaPlayerAndroid::pause() { |
| 299 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 295 Pause(true); | 300 Pause(true); |
| 296 } | 301 } |
| 297 | 302 |
| 298 void WebMediaPlayerAndroid::seek(double seconds) { | 303 void WebMediaPlayerAndroid::seek(double seconds) { |
| 299 DCHECK(main_thread_checker_.CalledOnValidThread()); | 304 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 300 DVLOG(1) << __FUNCTION__ << "(" << seconds << ")"; | 305 DVLOG(1) << __FUNCTION__ << "(" << seconds << ")"; |
| 301 | 306 |
| 302 base::TimeDelta new_seek_time = ConvertSecondsToTimestamp(seconds); | 307 base::TimeDelta new_seek_time = ConvertSecondsToTimestamp(seconds); |
| 303 | 308 |
| 304 if (seeking_) { | 309 if (seeking_) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 | 346 |
| 342 bool WebMediaPlayerAndroid::supportsSave() const { | 347 bool WebMediaPlayerAndroid::supportsSave() const { |
| 343 return false; | 348 return false; |
| 344 } | 349 } |
| 345 | 350 |
| 346 void WebMediaPlayerAndroid::setRate(double rate) { | 351 void WebMediaPlayerAndroid::setRate(double rate) { |
| 347 NOTIMPLEMENTED(); | 352 NOTIMPLEMENTED(); |
| 348 } | 353 } |
| 349 | 354 |
| 350 void WebMediaPlayerAndroid::setVolume(double volume) { | 355 void WebMediaPlayerAndroid::setVolume(double volume) { |
| 356 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 351 player_manager_->SetVolume(player_id_, volume); | 357 player_manager_->SetVolume(player_id_, volume); |
| 352 } | 358 } |
| 353 | 359 |
| 354 bool WebMediaPlayerAndroid::hasVideo() const { | 360 bool WebMediaPlayerAndroid::hasVideo() const { |
| 361 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 355 // If we have obtained video size information before, use it. | 362 // If we have obtained video size information before, use it. |
| 356 if (has_size_info_) | 363 if (has_size_info_) |
| 357 return !natural_size_.isEmpty(); | 364 return !natural_size_.isEmpty(); |
| 358 | 365 |
| 359 // TODO(qinmin): need a better method to determine whether the current media | 366 // TODO(qinmin): need a better method to determine whether the current media |
| 360 // content contains video. Android does not provide any function to do | 367 // content contains video. Android does not provide any function to do |
| 361 // this. | 368 // this. |
| 362 // We don't know whether the current media content has video unless | 369 // We don't know whether the current media content has video unless |
| 363 // the player is prepared. If the player is not prepared, we fall back | 370 // the player is prepared. If the player is not prepared, we fall back |
| 364 // to the mime-type. There may be no mime-type on a redirect URL. | 371 // to the mime-type. There may be no mime-type on a redirect URL. |
| 365 // In that case, we conservatively assume it contains video so that | 372 // In that case, we conservatively assume it contains video so that |
| 366 // enterfullscreen call will not fail. | 373 // enterfullscreen call will not fail. |
| 367 if (!url_.has_path()) | 374 if (!url_.has_path()) |
| 368 return false; | 375 return false; |
| 369 std::string mime; | 376 std::string mime; |
| 370 if (!net::GetMimeTypeFromFile(base::FilePath(url_.path()), &mime)) | 377 if (!net::GetMimeTypeFromFile(base::FilePath(url_.path()), &mime)) |
| 371 return true; | 378 return true; |
| 372 return mime.find("audio/") == std::string::npos; | 379 return mime.find("audio/") == std::string::npos; |
| 373 } | 380 } |
| 374 | 381 |
| 375 bool WebMediaPlayerAndroid::hasAudio() const { | 382 bool WebMediaPlayerAndroid::hasAudio() const { |
| 383 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 376 if (!url_.has_path()) | 384 if (!url_.has_path()) |
| 377 return false; | 385 return false; |
| 378 std::string mime; | 386 std::string mime; |
| 379 if (!net::GetMimeTypeFromFile(base::FilePath(url_.path()), &mime)) | 387 if (!net::GetMimeTypeFromFile(base::FilePath(url_.path()), &mime)) |
| 380 return true; | 388 return true; |
| 381 | 389 |
| 382 if (mime.find("audio/") != std::string::npos || | 390 if (mime.find("audio/") != std::string::npos || |
| 383 mime.find("video/") != std::string::npos || | 391 mime.find("video/") != std::string::npos || |
| 384 mime.find("application/ogg") != std::string::npos) { | 392 mime.find("application/ogg") != std::string::npos) { |
| 385 return true; | 393 return true; |
| 386 } | 394 } |
| 387 return false; | 395 return false; |
| 388 } | 396 } |
| 389 | 397 |
| 390 bool WebMediaPlayerAndroid::paused() const { | 398 bool WebMediaPlayerAndroid::paused() const { |
| 391 return !is_playing_; | 399 return !is_playing_; |
| 392 } | 400 } |
| 393 | 401 |
| 394 bool WebMediaPlayerAndroid::seeking() const { | 402 bool WebMediaPlayerAndroid::seeking() const { |
| 395 return seeking_; | 403 return seeking_; |
| 396 } | 404 } |
| 397 | 405 |
| 398 double WebMediaPlayerAndroid::duration() const { | 406 double WebMediaPlayerAndroid::duration() const { |
| 407 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 399 // HTML5 spec requires duration to be NaN if readyState is HAVE_NOTHING | 408 // HTML5 spec requires duration to be NaN if readyState is HAVE_NOTHING |
| 400 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) | 409 if (ready_state_ == WebMediaPlayer::ReadyStateHaveNothing) |
| 401 return std::numeric_limits<double>::quiet_NaN(); | 410 return std::numeric_limits<double>::quiet_NaN(); |
| 402 | 411 |
| 403 if (duration_ == media::kInfiniteDuration()) | 412 if (duration_ == media::kInfiniteDuration()) |
| 404 return std::numeric_limits<double>::infinity(); | 413 return std::numeric_limits<double>::infinity(); |
| 405 | 414 |
| 406 return duration_.InSecondsF(); | 415 return duration_.InSecondsF(); |
| 407 } | 416 } |
| 408 | 417 |
| 409 double WebMediaPlayerAndroid::timelineOffset() const { | 418 double WebMediaPlayerAndroid::timelineOffset() const { |
| 419 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 410 base::Time timeline_offset; | 420 base::Time timeline_offset; |
| 411 if (media_source_delegate_) | 421 if (media_source_delegate_) |
| 412 timeline_offset = media_source_delegate_->GetTimelineOffset(); | 422 timeline_offset = media_source_delegate_->GetTimelineOffset(); |
| 413 | 423 |
| 414 if (timeline_offset.is_null()) | 424 if (timeline_offset.is_null()) |
| 415 return std::numeric_limits<double>::quiet_NaN(); | 425 return std::numeric_limits<double>::quiet_NaN(); |
| 416 | 426 |
| 417 return timeline_offset.ToJsTime(); | 427 return timeline_offset.ToJsTime(); |
| 418 } | 428 } |
| 419 | 429 |
| 420 double WebMediaPlayerAndroid::currentTime() const { | 430 double WebMediaPlayerAndroid::currentTime() const { |
| 431 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 421 // If the player is processing a seek, return the seek time. | 432 // If the player is processing a seek, return the seek time. |
| 422 // Blink may still query us if updatePlaybackState() occurs while seeking. | 433 // Blink may still query us if updatePlaybackState() occurs while seeking. |
| 423 if (seeking()) { | 434 if (seeking()) { |
| 424 return pending_seek_ ? | 435 return pending_seek_ ? |
| 425 pending_seek_time_.InSecondsF() : seek_time_.InSecondsF(); | 436 pending_seek_time_.InSecondsF() : seek_time_.InSecondsF(); |
| 426 } | 437 } |
| 427 | 438 |
| 428 return current_time_; | 439 return current_time_; |
| 429 } | 440 } |
| 430 | 441 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 459 bool ret = did_loading_progress_; | 470 bool ret = did_loading_progress_; |
| 460 did_loading_progress_ = false; | 471 did_loading_progress_ = false; |
| 461 return ret; | 472 return ret; |
| 462 } | 473 } |
| 463 | 474 |
| 464 bool WebMediaPlayerAndroid::EnsureTextureBackedSkBitmap(GrContext* gr, | 475 bool WebMediaPlayerAndroid::EnsureTextureBackedSkBitmap(GrContext* gr, |
| 465 SkBitmap& bitmap, | 476 SkBitmap& bitmap, |
| 466 const WebSize& size, | 477 const WebSize& size, |
| 467 GrSurfaceOrigin origin, | 478 GrSurfaceOrigin origin, |
| 468 GrPixelConfig config) { | 479 GrPixelConfig config) { |
| 480 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 469 if (!bitmap.getTexture() || bitmap.width() != size.width | 481 if (!bitmap.getTexture() || bitmap.width() != size.width |
| 470 || bitmap.height() != size.height) { | 482 || bitmap.height() != size.height) { |
| 471 if (!gr) | 483 if (!gr) |
| 472 return false; | 484 return false; |
| 473 GrTextureDesc desc; | 485 GrTextureDesc desc; |
| 474 desc.fConfig = config; | 486 desc.fConfig = config; |
| 475 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; | 487 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; |
| 476 desc.fSampleCnt = 0; | 488 desc.fSampleCnt = 0; |
| 477 desc.fOrigin = origin; | 489 desc.fOrigin = origin; |
| 478 desc.fWidth = size.width; | 490 desc.fWidth = size.width; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 489 bitmap.setInfo(info); | 501 bitmap.setInfo(info); |
| 490 bitmap.setPixelRef(pixelRef)->unref(); | 502 bitmap.setPixelRef(pixelRef)->unref(); |
| 491 } | 503 } |
| 492 | 504 |
| 493 return true; | 505 return true; |
| 494 } | 506 } |
| 495 | 507 |
| 496 void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas, | 508 void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas, |
| 497 const blink::WebRect& rect, | 509 const blink::WebRect& rect, |
| 498 unsigned char alpha) { | 510 unsigned char alpha) { |
| 511 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 499 scoped_ptr<blink::WebGraphicsContext3DProvider> provider = | 512 scoped_ptr<blink::WebGraphicsContext3DProvider> provider = |
| 500 scoped_ptr<blink::WebGraphicsContext3DProvider>(blink::Platform::current( | 513 scoped_ptr<blink::WebGraphicsContext3DProvider>(blink::Platform::current( |
| 501 )->createSharedOffscreenGraphicsContext3DProvider()); | 514 )->createSharedOffscreenGraphicsContext3DProvider()); |
| 502 if (!provider) | 515 if (!provider) |
| 503 return; | 516 return; |
| 504 blink::WebGraphicsContext3D* context3D = provider->context3d(); | 517 blink::WebGraphicsContext3D* context3D = provider->context3d(); |
| 505 if (!context3D || !context3D->makeContextCurrent()) | 518 if (!context3D || !context3D->makeContextCurrent()) |
| 506 return; | 519 return; |
| 507 | 520 |
| 508 // Copy video texture into a RGBA texture based bitmap first as video texture | 521 // Copy video texture into a RGBA texture based bitmap first as video texture |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 537 } | 550 } |
| 538 | 551 |
| 539 bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( | 552 bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture( |
| 540 blink::WebGraphicsContext3D* web_graphics_context, | 553 blink::WebGraphicsContext3D* web_graphics_context, |
| 541 unsigned int texture, | 554 unsigned int texture, |
| 542 unsigned int level, | 555 unsigned int level, |
| 543 unsigned int internal_format, | 556 unsigned int internal_format, |
| 544 unsigned int type, | 557 unsigned int type, |
| 545 bool premultiply_alpha, | 558 bool premultiply_alpha, |
| 546 bool flip_y) { | 559 bool flip_y) { |
| 560 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 547 // Don't allow clients to copy an encrypted video frame. | 561 // Don't allow clients to copy an encrypted video frame. |
| 548 if (needs_external_surface_) | 562 if (needs_external_surface_) |
| 549 return false; | 563 return false; |
| 550 | 564 |
| 551 scoped_refptr<VideoFrame> video_frame; | 565 scoped_refptr<VideoFrame> video_frame; |
| 552 { | 566 { |
| 553 base::AutoLock auto_lock(current_frame_lock_); | 567 base::AutoLock auto_lock(current_frame_lock_); |
| 554 video_frame = current_frame_; | 568 video_frame = current_frame_; |
| 555 } | 569 } |
| 556 | 570 |
| 557 if (!video_frame || | 571 if (!video_frame || |
| 558 video_frame->format() != media::VideoFrame::NATIVE_TEXTURE) | 572 video_frame->format() != media::VideoFrame::NATIVE_TEXTURE) |
| 559 return false; | 573 return false; |
| 560 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); | 574 const gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder(); |
| 561 DCHECK((!is_remote_ && | 575 DCHECK((!is_remote_ && |
| 562 mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) || | 576 mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) || |
| 563 (is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_2D)); | 577 (is_remote_ && mailbox_holder->texture_target == GL_TEXTURE_2D)); |
| 564 | 578 |
| 565 // For hidden video element (with style "display:none"), ensure the texture | |
| 566 // size is set. | |
| 567 if (!is_remote_ && | |
| 568 (cached_stream_texture_size_.width != natural_size_.width || | |
| 569 cached_stream_texture_size_.height != natural_size_.height)) { | |
| 570 stream_texture_factory_->SetStreamTextureSize( | |
| 571 stream_id_, gfx::Size(natural_size_.width, natural_size_.height)); | |
| 572 cached_stream_texture_size_ = natural_size_; | |
| 573 } | |
| 574 | |
| 575 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point); | 579 web_graphics_context->waitSyncPoint(mailbox_holder->sync_point); |
| 576 | 580 |
| 577 // Ensure the target of texture is set before copyTextureCHROMIUM, otherwise | 581 // Ensure the target of texture is set before copyTextureCHROMIUM, otherwise |
| 578 // an invalid texture target may be used for copy texture. | 582 // an invalid texture target may be used for copy texture. |
| 579 uint32 src_texture = web_graphics_context->createAndConsumeTextureCHROMIUM( | 583 uint32 src_texture = web_graphics_context->createAndConsumeTextureCHROMIUM( |
| 580 mailbox_holder->texture_target, mailbox_holder->mailbox.name); | 584 mailbox_holder->texture_target, mailbox_holder->mailbox.name); |
| 581 | 585 |
| 582 // The video is stored in an unmultiplied format, so premultiply if | 586 // The video is stored in an unmultiplied format, so premultiply if |
| 583 // necessary. | 587 // necessary. |
| 584 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, | 588 web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 598 | 602 |
| 599 web_graphics_context->deleteTexture(src_texture); | 603 web_graphics_context->deleteTexture(src_texture); |
| 600 web_graphics_context->flush(); | 604 web_graphics_context->flush(); |
| 601 | 605 |
| 602 SyncPointClientImpl client(web_graphics_context); | 606 SyncPointClientImpl client(web_graphics_context); |
| 603 video_frame->UpdateReleaseSyncPoint(&client); | 607 video_frame->UpdateReleaseSyncPoint(&client); |
| 604 return true; | 608 return true; |
| 605 } | 609 } |
| 606 | 610 |
| 607 bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const { | 611 bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const { |
| 612 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 608 if (info_loader_) | 613 if (info_loader_) |
| 609 return info_loader_->HasSingleOrigin(); | 614 return info_loader_->HasSingleOrigin(); |
| 610 // The info loader may have failed. | 615 // The info loader may have failed. |
| 611 if (player_type_ == MEDIA_PLAYER_TYPE_URL) | 616 if (player_type_ == MEDIA_PLAYER_TYPE_URL) |
| 612 return false; | 617 return false; |
| 613 return true; | 618 return true; |
| 614 } | 619 } |
| 615 | 620 |
| 616 bool WebMediaPlayerAndroid::didPassCORSAccessCheck() const { | 621 bool WebMediaPlayerAndroid::didPassCORSAccessCheck() const { |
| 622 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 617 if (info_loader_) | 623 if (info_loader_) |
| 618 return info_loader_->DidPassCORSAccessCheck(); | 624 return info_loader_->DidPassCORSAccessCheck(); |
| 619 return false; | 625 return false; |
| 620 } | 626 } |
| 621 | 627 |
| 622 double WebMediaPlayerAndroid::mediaTimeForTimeValue(double timeValue) const { | 628 double WebMediaPlayerAndroid::mediaTimeForTimeValue(double timeValue) const { |
| 623 return ConvertSecondsToTimestamp(timeValue).InSecondsF(); | 629 return ConvertSecondsToTimestamp(timeValue).InSecondsF(); |
| 624 } | 630 } |
| 625 | 631 |
| 626 unsigned WebMediaPlayerAndroid::decodedFrameCount() const { | 632 unsigned WebMediaPlayerAndroid::decodedFrameCount() const { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 646 | 652 |
| 647 unsigned WebMediaPlayerAndroid::videoDecodedByteCount() const { | 653 unsigned WebMediaPlayerAndroid::videoDecodedByteCount() const { |
| 648 if (media_source_delegate_) | 654 if (media_source_delegate_) |
| 649 return media_source_delegate_->VideoDecodedByteCount(); | 655 return media_source_delegate_->VideoDecodedByteCount(); |
| 650 NOTIMPLEMENTED(); | 656 NOTIMPLEMENTED(); |
| 651 return 0; | 657 return 0; |
| 652 } | 658 } |
| 653 | 659 |
| 654 void WebMediaPlayerAndroid::OnMediaMetadataChanged( | 660 void WebMediaPlayerAndroid::OnMediaMetadataChanged( |
| 655 const base::TimeDelta& duration, int width, int height, bool success) { | 661 const base::TimeDelta& duration, int width, int height, bool success) { |
| 662 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 656 bool need_to_signal_duration_changed = false; | 663 bool need_to_signal_duration_changed = false; |
| 657 | 664 |
| 658 if (url_.SchemeIs("file")) | 665 if (url_.SchemeIs("file")) |
| 659 UpdateNetworkState(WebMediaPlayer::NetworkStateLoaded); | 666 UpdateNetworkState(WebMediaPlayer::NetworkStateLoaded); |
| 660 | 667 |
| 661 // Update duration, if necessary, prior to ready state updates that may | 668 // Update duration, if necessary, prior to ready state updates that may |
| 662 // cause duration() query. | 669 // cause duration() query. |
| 663 if (!ignore_metadata_duration_change_ && duration_ != duration) { | 670 if (!ignore_metadata_duration_change_ && duration_ != duration) { |
| 664 duration_ = duration; | 671 duration_ = duration; |
| 665 | 672 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 case MediaPlayerAndroid::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: | 756 case MediaPlayerAndroid::MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: |
| 750 UpdateNetworkState(WebMediaPlayer::NetworkStateFormatError); | 757 UpdateNetworkState(WebMediaPlayer::NetworkStateFormatError); |
| 751 break; | 758 break; |
| 752 case MediaPlayerAndroid::MEDIA_ERROR_INVALID_CODE: | 759 case MediaPlayerAndroid::MEDIA_ERROR_INVALID_CODE: |
| 753 break; | 760 break; |
| 754 } | 761 } |
| 755 client_->repaint(); | 762 client_->repaint(); |
| 756 } | 763 } |
| 757 | 764 |
| 758 void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) { | 765 void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) { |
| 766 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 759 has_size_info_ = true; | 767 has_size_info_ = true; |
| 760 if (natural_size_.width == width && natural_size_.height == height) | 768 if (natural_size_.width == width && natural_size_.height == height) |
| 761 return; | 769 return; |
| 762 | 770 |
| 763 #if defined(VIDEO_HOLE) | 771 #if defined(VIDEO_HOLE) |
| 764 // Use H/W surface for encrypted video. | 772 // Use H/W surface for encrypted video. |
| 765 // TODO(qinmin): Change this so that only EME needs the H/W surface | 773 // TODO(qinmin): Change this so that only EME needs the H/W surface |
| 766 if (force_use_overlay_embedded_video_ || | 774 if (force_use_overlay_embedded_video_ || |
| 767 (media_source_delegate_ && media_source_delegate_->IsVideoEncrypted() && | 775 (media_source_delegate_ && media_source_delegate_->IsVideoEncrypted() && |
| 768 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo())) { | 776 player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo())) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 780 // may play without a surface texture. When we finally get the valid video | 788 // may play without a surface texture. When we finally get the valid video |
| 781 // size here, we should call EstablishSurfaceTexturePeer() if it has not been | 789 // size here, we should call EstablishSurfaceTexturePeer() if it has not been |
| 782 // previously called. | 790 // previously called. |
| 783 if (!paused() && needs_establish_peer_) | 791 if (!paused() && needs_establish_peer_) |
| 784 EstablishSurfaceTexturePeer(); | 792 EstablishSurfaceTexturePeer(); |
| 785 | 793 |
| 786 natural_size_.width = width; | 794 natural_size_.width = width; |
| 787 natural_size_.height = height; | 795 natural_size_.height = height; |
| 788 ReallocateVideoFrame(); | 796 ReallocateVideoFrame(); |
| 789 | 797 |
| 798 // For hidden video element (with style "display:none"), ensure the texture | |
| 799 // size is set. | |
| 800 if (!is_remote_) { | |
| 801 stream_texture_factory_->SetStreamTextureSize( | |
| 802 stream_id_, gfx::Size(natural_size_.width, natural_size_.height)); | |
| 803 } | |
| 804 | |
| 790 // Lazily allocate compositing layer. | 805 // Lazily allocate compositing layer. |
| 791 if (!video_weblayer_) { | 806 if (!video_weblayer_) { |
| 792 video_weblayer_.reset(new WebLayerImpl(cc::VideoLayer::Create(this))); | 807 video_weblayer_.reset(new WebLayerImpl(cc::VideoLayer::Create(this))); |
| 793 client_->setWebLayer(video_weblayer_.get()); | 808 client_->setWebLayer(video_weblayer_.get()); |
| 794 } | 809 } |
| 795 | 810 |
| 796 // TODO(qinmin): This is a hack. We need the media element to stop showing the | 811 // TODO(qinmin): This is a hack. We need the media element to stop showing the |
| 797 // poster image by forcing it to call setDisplayMode(video). Should move the | 812 // poster image by forcing it to call setDisplayMode(video). Should move the |
| 798 // logic into HTMLMediaElement.cpp. | 813 // logic into HTMLMediaElement.cpp. |
| 799 client_->timeChanged(); | 814 client_->timeChanged(); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 947 frame_->document().url()); | 962 frame_->document().url()); |
| 948 } | 963 } |
| 949 | 964 |
| 950 void WebMediaPlayerAndroid::Pause(bool is_media_related_action) { | 965 void WebMediaPlayerAndroid::Pause(bool is_media_related_action) { |
| 951 player_manager_->Pause(player_id_, is_media_related_action); | 966 player_manager_->Pause(player_id_, is_media_related_action); |
| 952 UpdatePlayingState(false); | 967 UpdatePlayingState(false); |
| 953 } | 968 } |
| 954 | 969 |
| 955 void WebMediaPlayerAndroid::DrawRemotePlaybackText( | 970 void WebMediaPlayerAndroid::DrawRemotePlaybackText( |
| 956 const std::string& remote_playback_message) { | 971 const std::string& remote_playback_message) { |
| 957 | |
| 958 DCHECK(main_thread_checker_.CalledOnValidThread()); | 972 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 959 if (!video_weblayer_) | 973 if (!video_weblayer_) |
| 960 return; | 974 return; |
| 961 | 975 |
| 962 // TODO(johnme): Should redraw this frame if the layer bounds change; but | 976 // TODO(johnme): Should redraw this frame if the layer bounds change; but |
| 963 // there seems no easy way to listen for the layer resizing (as opposed to | 977 // there seems no easy way to listen for the layer resizing (as opposed to |
| 964 // OnVideoSizeChanged, which is when the frame sizes of the video file | 978 // OnVideoSizeChanged, which is when the frame sizes of the video file |
| 965 // change). Perhaps have to poll (on main thread of course)? | 979 // change). Perhaps have to poll (on main thread of course)? |
| 966 gfx::Size video_size_css_px = video_weblayer_->bounds(); | 980 gfx::Size video_size_css_px = video_weblayer_->bounds(); |
| 967 float device_scale_factor = frame_->view()->deviceScaleFactor(); | 981 float device_scale_factor = frame_->view()->deviceScaleFactor(); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1069 remote_playback_texture_id)), | 1083 remote_playback_texture_id)), |
| 1070 canvas_size /* coded_size */, | 1084 canvas_size /* coded_size */, |
| 1071 gfx::Rect(canvas_size) /* visible_rect */, | 1085 gfx::Rect(canvas_size) /* visible_rect */, |
| 1072 canvas_size /* natural_size */, | 1086 canvas_size /* natural_size */, |
| 1073 base::TimeDelta() /* timestamp */, | 1087 base::TimeDelta() /* timestamp */, |
| 1074 VideoFrame::ReadPixelsCB()); | 1088 VideoFrame::ReadPixelsCB()); |
| 1075 SetCurrentFrameInternal(new_frame); | 1089 SetCurrentFrameInternal(new_frame); |
| 1076 } | 1090 } |
| 1077 | 1091 |
| 1078 void WebMediaPlayerAndroid::ReallocateVideoFrame() { | 1092 void WebMediaPlayerAndroid::ReallocateVideoFrame() { |
| 1093 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 1079 if (needs_external_surface_) { | 1094 if (needs_external_surface_) { |
| 1080 // VideoFrame::CreateHoleFrame is only defined under VIDEO_HOLE. | 1095 // VideoFrame::CreateHoleFrame is only defined under VIDEO_HOLE. |
| 1081 #if defined(VIDEO_HOLE) | 1096 #if defined(VIDEO_HOLE) |
| 1082 if (!natural_size_.isEmpty()) { | 1097 if (!natural_size_.isEmpty()) { |
| 1083 scoped_refptr<VideoFrame> new_frame = | 1098 scoped_refptr<VideoFrame> new_frame = |
| 1084 VideoFrame::CreateHoleFrame(natural_size_); | 1099 VideoFrame::CreateHoleFrame(natural_size_); |
| 1085 SetCurrentFrameInternal(new_frame); | 1100 SetCurrentFrameInternal(new_frame); |
| 1086 // Force the client to grab the hole frame. | 1101 // Force the client to grab the hole frame. |
| 1087 client_->repaint(); | 1102 client_->repaint(); |
| 1088 } | 1103 } |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1113 | 1128 |
| 1114 void WebMediaPlayerAndroid::SetVideoFrameProviderClient( | 1129 void WebMediaPlayerAndroid::SetVideoFrameProviderClient( |
| 1115 cc::VideoFrameProvider::Client* client) { | 1130 cc::VideoFrameProvider::Client* client) { |
| 1116 // This is called from both the main renderer thread and the compositor | 1131 // This is called from both the main renderer thread and the compositor |
| 1117 // thread (when the main thread is blocked). | 1132 // thread (when the main thread is blocked). |
| 1118 if (video_frame_provider_client_) | 1133 if (video_frame_provider_client_) |
| 1119 video_frame_provider_client_->StopUsingProvider(); | 1134 video_frame_provider_client_->StopUsingProvider(); |
| 1120 video_frame_provider_client_ = client; | 1135 video_frame_provider_client_ = client; |
| 1121 | 1136 |
| 1122 // Set the callback target when a frame is produced. | 1137 // Set the callback target when a frame is produced. |
| 1123 if (stream_texture_proxy_) | 1138 if (stream_texture_proxy_) { |
| 1124 stream_texture_proxy_->SetClient(client); | 1139 stream_texture_proxy_->SetClient(client); |
| 1140 // If client exists, the compositor thread calls it. At that time, | |
| 1141 // stream_id_, needs_external_surface_, is_remote_ can be accessed because | |
| 1142 // the main thread is blocked. | |
| 1143 if (client && !stream_texture_proxy_initialized_ && stream_id_ && | |
| 1144 !needs_external_surface_ && !is_remote_) { | |
| 1145 stream_texture_proxy_->BindToCurrentThread(stream_id_); | |
|
qinmin
2014/08/08 22:02:58
I don't think this is correct, the stream_texture_
dshwang
2014/08/09 06:01:26
As above comments, I bind the proxy to the composi
qinmin
2014/08/10 18:33:51
i see, i missed the non-null check on client.
On
| |
| 1146 stream_texture_proxy_initialized_ = true; | |
| 1147 } | |
| 1148 } | |
| 1125 } | 1149 } |
| 1126 | 1150 |
| 1127 void WebMediaPlayerAndroid::SetCurrentFrameInternal( | 1151 void WebMediaPlayerAndroid::SetCurrentFrameInternal( |
| 1128 scoped_refptr<media::VideoFrame>& video_frame) { | 1152 scoped_refptr<media::VideoFrame>& video_frame) { |
| 1153 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 1129 base::AutoLock auto_lock(current_frame_lock_); | 1154 base::AutoLock auto_lock(current_frame_lock_); |
| 1130 current_frame_ = video_frame; | 1155 current_frame_ = video_frame; |
| 1131 } | 1156 } |
| 1132 | 1157 |
| 1133 scoped_refptr<media::VideoFrame> WebMediaPlayerAndroid::GetCurrentFrame() { | 1158 scoped_refptr<media::VideoFrame> WebMediaPlayerAndroid::GetCurrentFrame() { |
| 1134 scoped_refptr<VideoFrame> video_frame; | 1159 scoped_refptr<VideoFrame> video_frame; |
| 1135 { | 1160 { |
| 1136 base::AutoLock auto_lock(current_frame_lock_); | 1161 base::AutoLock auto_lock(current_frame_lock_); |
| 1137 video_frame = current_frame_; | 1162 video_frame = current_frame_; |
| 1138 } | 1163 } |
| 1139 | 1164 |
| 1140 if (!stream_texture_proxy_initialized_ && stream_texture_proxy_ && | |
| 1141 stream_id_ && !needs_external_surface_ && !is_remote_) { | |
| 1142 gfx::Size natural_size = video_frame->natural_size(); | |
| 1143 // TODO(sievers): These variables are accessed on the wrong thread here. | |
| 1144 stream_texture_proxy_->BindToCurrentThread(stream_id_); | |
| 1145 stream_texture_factory_->SetStreamTextureSize(stream_id_, natural_size); | |
| 1146 stream_texture_proxy_initialized_ = true; | |
| 1147 cached_stream_texture_size_ = natural_size; | |
| 1148 } | |
| 1149 | |
| 1150 return video_frame; | 1165 return video_frame; |
| 1151 } | 1166 } |
| 1152 | 1167 |
| 1153 void WebMediaPlayerAndroid::PutCurrentFrame( | 1168 void WebMediaPlayerAndroid::PutCurrentFrame( |
| 1154 const scoped_refptr<media::VideoFrame>& frame) { | 1169 const scoped_refptr<media::VideoFrame>& frame) { |
| 1155 } | 1170 } |
| 1156 | 1171 |
| 1157 void WebMediaPlayerAndroid::TryCreateStreamTextureProxyIfNeeded() { | 1172 void WebMediaPlayerAndroid::TryCreateStreamTextureProxyIfNeeded() { |
| 1173 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 1158 // Already created. | 1174 // Already created. |
| 1159 if (stream_texture_proxy_) | 1175 if (stream_texture_proxy_) |
| 1160 return; | 1176 return; |
| 1161 | 1177 |
| 1162 // No factory to create proxy. | 1178 // No factory to create proxy. |
| 1163 if (!stream_texture_factory_) | 1179 if (!stream_texture_factory_) |
| 1164 return; | 1180 return; |
| 1165 | 1181 |
| 1166 stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy()); | 1182 stream_texture_proxy_.reset(stream_texture_factory_->CreateProxy()); |
| 1167 if (needs_establish_peer_ && stream_texture_proxy_) { | 1183 if (needs_establish_peer_ && stream_texture_proxy_) { |
| 1168 DoCreateStreamTexture(); | 1184 DoCreateStreamTexture(); |
| 1169 ReallocateVideoFrame(); | 1185 ReallocateVideoFrame(); |
| 1170 } | 1186 } |
| 1171 | 1187 |
| 1172 if (stream_texture_proxy_ && video_frame_provider_client_) | 1188 if (stream_texture_proxy_ && video_frame_provider_client_) |
| 1173 stream_texture_proxy_->SetClient(video_frame_provider_client_); | 1189 stream_texture_proxy_->SetClient(video_frame_provider_client_); |
| 1174 } | 1190 } |
| 1175 | 1191 |
| 1176 void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() { | 1192 void WebMediaPlayerAndroid::EstablishSurfaceTexturePeer() { |
| 1193 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 1177 if (!stream_texture_proxy_) | 1194 if (!stream_texture_proxy_) |
| 1178 return; | 1195 return; |
| 1179 | 1196 |
| 1180 if (stream_texture_factory_.get() && stream_id_) | 1197 if (stream_texture_factory_.get() && stream_id_) |
| 1181 stream_texture_factory_->EstablishPeer(stream_id_, player_id_); | 1198 stream_texture_factory_->EstablishPeer(stream_id_, player_id_); |
| 1182 needs_establish_peer_ = false; | 1199 needs_establish_peer_ = false; |
| 1183 } | 1200 } |
| 1184 | 1201 |
| 1185 void WebMediaPlayerAndroid::DoCreateStreamTexture() { | 1202 void WebMediaPlayerAndroid::DoCreateStreamTexture() { |
| 1203 DCHECK(main_thread_checker_.CalledOnValidThread()); | |
| 1186 DCHECK(!stream_id_); | 1204 DCHECK(!stream_id_); |
| 1187 DCHECK(!texture_id_); | 1205 DCHECK(!texture_id_); |
| 1188 stream_id_ = stream_texture_factory_->CreateStreamTexture( | 1206 stream_id_ = stream_texture_factory_->CreateStreamTexture( |
| 1189 kGLTextureExternalOES, &texture_id_, &texture_mailbox_); | 1207 kGLTextureExternalOES, &texture_id_, &texture_mailbox_); |
| 1190 } | 1208 } |
| 1191 | 1209 |
| 1192 void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) { | 1210 void WebMediaPlayerAndroid::SetNeedsEstablishPeer(bool needs_establish_peer) { |
| 1193 needs_establish_peer_ = needs_establish_peer; | 1211 needs_establish_peer_ = needs_establish_peer; |
| 1194 } | 1212 } |
| 1195 | 1213 |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1602 player_manager_->EnterFullscreen(player_id_, frame_); | 1620 player_manager_->EnterFullscreen(player_id_, frame_); |
| 1603 SetNeedsEstablishPeer(false); | 1621 SetNeedsEstablishPeer(false); |
| 1604 } | 1622 } |
| 1605 } | 1623 } |
| 1606 | 1624 |
| 1607 bool WebMediaPlayerAndroid::canEnterFullscreen() const { | 1625 bool WebMediaPlayerAndroid::canEnterFullscreen() const { |
| 1608 return player_manager_->CanEnterFullscreen(frame_); | 1626 return player_manager_->CanEnterFullscreen(frame_); |
| 1609 } | 1627 } |
| 1610 | 1628 |
| 1611 } // namespace content | 1629 } // namespace content |
| OLD | NEW |