Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "media/gpu/android_video_decode_accelerator.h" | 5 #include "media/gpu/android_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 332 DCHECK(cdm_registration_id_); | 332 DCHECK(cdm_registration_id_); |
| 333 media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_); | 333 media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_); |
| 334 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 334 #endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 335 } | 335 } |
| 336 | 336 |
| 337 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, | 337 bool AndroidVideoDecodeAccelerator::Initialize(const Config& config, |
| 338 Client* client) { | 338 Client* client) { |
| 339 DCHECK(!media_codec_); | 339 DCHECK(!media_codec_); |
| 340 DCHECK(thread_checker_.CalledOnValidThread()); | 340 DCHECK(thread_checker_.CalledOnValidThread()); |
| 341 TRACE_EVENT0("media", "AVDA::Initialize"); | 341 TRACE_EVENT0("media", "AVDA::Initialize"); |
| 342 | |
| 343 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); | 342 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); |
| 344 | 343 |
| 345 if (make_context_current_cb_.is_null() || get_gles2_decoder_cb_.is_null()) { | 344 if (make_context_current_cb_.is_null() || get_gles2_decoder_cb_.is_null()) { |
| 346 NOTREACHED() << "GL callbacks are required for this VDA"; | 345 NOTREACHED() << "GL callbacks are required for this VDA"; |
| 347 return false; | 346 return false; |
| 348 } | 347 } |
| 349 | 348 |
| 350 if (config.output_mode != Config::OutputMode::ALLOCATE) { | 349 if (config.output_mode != Config::OutputMode::ALLOCATE) { |
| 351 NOTREACHED() << "Only ALLOCATE OutputMode is supported by this VDA"; | 350 NOTREACHED() << "Only ALLOCATE OutputMode is supported by this VDA"; |
| 352 return false; | 351 return false; |
| 353 } | 352 } |
| 354 | 353 |
| 355 DCHECK(client); | 354 DCHECK(client); |
| 356 client_ = client; | 355 client_ = client; |
| 357 codec_config_ = new CodecConfig(); | 356 codec_config_ = new CodecConfig(); |
| 358 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile); | 357 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile); |
| 359 codec_config_->initial_expected_coded_size_ = | 358 codec_config_->initial_expected_coded_size_ = |
| 360 config.initial_expected_coded_size; | 359 config.initial_expected_coded_size; |
| 361 is_encrypted_ = config.is_encrypted; | 360 is_encrypted_ = config.is_encrypted; |
| 362 | 361 |
| 363 bool profile_supported = codec_config_->codec_ == media::kCodecVP8 || | |
| 364 codec_config_->codec_ == media::kCodecVP9 || | |
| 365 codec_config_->codec_ == media::kCodecH264; | |
| 366 | |
| 367 // We signalled that we support deferred initialization, so see if the client | 362 // We signalled that we support deferred initialization, so see if the client |
| 368 // does also. | 363 // does also. |
| 369 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; | 364 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; |
| 370 | 365 |
| 366 bool profile_supported = codec_config_->codec_ == media::kCodecVP8 || | |
| 367 codec_config_->codec_ == media::kCodecVP9 || | |
| 368 codec_config_->codec_ == media::kCodecH264; | |
| 371 if (!profile_supported) { | 369 if (!profile_supported) { |
| 372 LOG(ERROR) << "Unsupported profile: " << config.profile; | 370 LOG(ERROR) << "Unsupported profile: " << config.profile; |
| 373 return false; | 371 return false; |
| 374 } | 372 } |
| 375 | 373 |
| 376 // For encrypted streams we postpone configuration until MediaCrypto is | |
| 377 // available. | |
| 378 DCHECK(!is_encrypted_ || deferred_initialization_pending_); | |
|
watk
2016/05/09 23:39:59
DCHECK is below now
| |
| 379 | |
| 380 // Only use MediaCodec for VP8/9 if it's likely backed by hardware | 374 // Only use MediaCodec for VP8/9 if it's likely backed by hardware |
| 381 // or if the stream is encrypted. | 375 // or if the stream is encrypted. |
| 382 if ((codec_config_->codec_ == media::kCodecVP8 || | 376 if ((codec_config_->codec_ == media::kCodecVP8 || |
| 383 codec_config_->codec_ == media::kCodecVP9) && | 377 codec_config_->codec_ == media::kCodecVP9) && |
| 384 !is_encrypted_ && | 378 !is_encrypted_ && |
| 385 media::VideoCodecBridge::IsKnownUnaccelerated( | 379 media::VideoCodecBridge::IsKnownUnaccelerated( |
| 386 codec_config_->codec_, media::MEDIA_CODEC_DECODER)) { | 380 codec_config_->codec_, media::MEDIA_CODEC_DECODER)) { |
| 387 DVLOG(1) << "Initialization failed: " | 381 DVLOG(1) << "Initialization failed: " |
| 388 << (codec_config_->codec_ == media::kCodecVP8 ? "vp8" : "vp9") | 382 << (codec_config_->codec_ == media::kCodecVP8 ? "vp8" : "vp9") |
| 389 << " is not hardware accelerated"; | 383 << " is not hardware accelerated"; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 scoped_refptr<gfx::SurfaceTexture> surface_texture = | 420 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
| 427 strategy_->GetSurfaceTexture(); | 421 strategy_->GetSurfaceTexture(); |
| 428 if (surface_texture) { | 422 if (surface_texture) { |
| 429 on_frame_available_handler_ = | 423 on_frame_available_handler_ = |
| 430 new OnFrameAvailableHandler(this, surface_texture); | 424 new OnFrameAvailableHandler(this, surface_texture); |
| 431 } | 425 } |
| 432 | 426 |
| 433 // Start the thread for async configuration, even if we don't need it now. | 427 // Start the thread for async configuration, even if we don't need it now. |
| 434 // ResetCodecState might rebuild the codec later, for example. | 428 // ResetCodecState might rebuild the codec later, for example. |
| 435 if (!g_avda_timer.Pointer()->StartThread(this)) { | 429 if (!g_avda_timer.Pointer()->StartThread(this)) { |
| 436 LOG(ERROR) << "Failed to start thread for AVDA timer"; | 430 LOG(ERROR) << "Failed to start AVDA thread"; |
|
watk
2016/05/09 23:39:59
The timer doesn't run on that thread.
| |
| 437 return false; | 431 return false; |
| 438 } | 432 } |
| 439 | 433 |
| 440 // If we are encrypted, then we aren't able to create the codec yet. | 434 // If we are encrypted, then we aren't able to create the codec yet. |
| 441 if (is_encrypted_) | 435 if (is_encrypted_) { |
| 436 DCHECK(deferred_initialization_pending_); | |
|
sandersd (OOO until July 31)
2016/05/10 00:09:54
We should handle this case gracefully (return fals
| |
| 437 InitializeCdm(config.cdm_id); | |
| 442 return true; | 438 return true; |
| 439 } | |
| 443 | 440 |
| 444 if (deferred_initialization_pending_) { | 441 if (deferred_initialization_pending_) { |
| 445 ConfigureMediaCodecAsynchronously(); | 442 ConfigureMediaCodecAsynchronously(); |
| 446 return true; | 443 return true; |
| 447 } | 444 } |
| 448 | 445 |
| 449 // If the client doesn't support deferred initialization (WebRTC), then we | 446 // If the client doesn't support deferred initialization (WebRTC), then we |
| 450 // should complete it now and return a meaningful result. | 447 // should complete it now and return a meaningful result. |
| 451 return ConfigureMediaCodecSynchronously(); | 448 return ConfigureMediaCodecSynchronously(); |
| 452 } | 449 } |
| 453 | 450 |
| 454 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { | |
|
watk
2016/05/09 23:39:59
I moved this block because it's now in the private
| |
| 455 DVLOG(2) << __FUNCTION__ << ": " << cdm_id; | |
| 456 | |
| 457 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | |
| 458 DCHECK(client_) << "SetCdm() must be called after Initialize()."; | |
| 459 | |
| 460 if (media_drm_bridge_cdm_context_) { | |
| 461 NOTREACHED() << "We do not support resetting CDM."; | |
| 462 NotifyInitializationComplete(false); | |
| 463 return; | |
| 464 } | |
| 465 | |
| 466 // Store the CDM to hold a reference to it. | |
| 467 cdm_for_reference_holding_only_ = media::MojoCdmService::LegacyGetCdm(cdm_id); | |
| 468 DCHECK(cdm_for_reference_holding_only_); | |
| 469 | |
| 470 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext. | |
| 471 media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>( | |
| 472 cdm_for_reference_holding_only_->GetCdmContext()); | |
| 473 DCHECK(media_drm_bridge_cdm_context_); | |
| 474 | |
| 475 // Register CDM callbacks. The callbacks registered will be posted back to | |
| 476 // this thread via BindToCurrentLoop. | |
| 477 | |
| 478 // Since |this| holds a reference to the |cdm_|, by the time the CDM is | |
| 479 // destructed, UnregisterPlayer() must have been called and |this| has been | |
| 480 // destructed as well. So the |cdm_unset_cb| will never have a chance to be | |
| 481 // called. | |
| 482 // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms. | |
| 483 cdm_registration_id_ = media_drm_bridge_cdm_context_->RegisterPlayer( | |
| 484 media::BindToCurrentLoop( | |
| 485 base::Bind(&AndroidVideoDecodeAccelerator::OnKeyAdded, | |
| 486 weak_this_factory_.GetWeakPtr())), | |
| 487 base::Bind(&base::DoNothing)); | |
| 488 | |
| 489 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(media::BindToCurrentLoop( | |
| 490 base::Bind(&AndroidVideoDecodeAccelerator::OnMediaCryptoReady, | |
| 491 weak_this_factory_.GetWeakPtr()))); | |
| 492 | |
| 493 // Postpone NotifyInitializationComplete() call till we create the MediaCodec | |
| 494 // after OnMediaCryptoReady(). | |
| 495 #else | |
| 496 | |
| 497 NOTIMPLEMENTED(); | |
| 498 NotifyInitializationComplete(false); | |
| 499 | |
| 500 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | |
| 501 } | |
| 502 | |
| 503 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { | 451 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { |
| 504 DCHECK(thread_checker_.CalledOnValidThread()); | 452 DCHECK(thread_checker_.CalledOnValidThread()); |
| 505 TRACE_EVENT0("media", "AVDA::DoIOTask"); | 453 TRACE_EVENT0("media", "AVDA::DoIOTask"); |
| 506 if (state_ == ERROR || state_ == WAITING_FOR_CODEC) | 454 if (state_ == ERROR || state_ == WAITING_FOR_CODEC) |
| 507 return; | 455 return; |
| 508 | 456 |
| 509 strategy_->MaybeRenderEarly(); | 457 strategy_->MaybeRenderEarly(); |
| 510 bool did_work = false, did_input = false, did_output = false; | 458 bool did_work = false, did_input = false, did_output = false; |
| 511 do { | 459 do { |
| 512 did_input = QueueInput(); | 460 did_input = QueueInput(); |
| (...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1291 const ::tracked_objects::Location& from_here, | 1239 const ::tracked_objects::Location& from_here, |
| 1292 media::VideoDecodeAccelerator::Error error) { | 1240 media::VideoDecodeAccelerator::Error error) { |
| 1293 base::MessageLoop::current()->PostDelayedTask( | 1241 base::MessageLoop::current()->PostDelayedTask( |
| 1294 from_here, | 1242 from_here, |
| 1295 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, | 1243 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, |
| 1296 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), | 1244 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), |
| 1297 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); | 1245 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); |
| 1298 state_ = ERROR; | 1246 state_ = ERROR; |
| 1299 } | 1247 } |
| 1300 | 1248 |
| 1249 void AndroidVideoDecodeAccelerator::InitializeCdm(int cdm_id) { | |
| 1250 DVLOG(2) << __FUNCTION__ << ": " << cdm_id; | |
| 1251 | |
| 1252 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | |
| 1253 NOTIMPLEMENTED(); | |
| 1254 NotifyInitializationComplete(false); | |
| 1255 #else | |
| 1256 // Store the CDM to hold a reference to it. | |
| 1257 cdm_for_reference_holding_only_ = media::MojoCdmService::LegacyGetCdm(cdm_id); | |
| 1258 DCHECK(cdm_for_reference_holding_only_); | |
| 1259 | |
| 1260 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext. | |
| 1261 media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>( | |
| 1262 cdm_for_reference_holding_only_->GetCdmContext()); | |
| 1263 DCHECK(media_drm_bridge_cdm_context_); | |
| 1264 | |
| 1265 // Register CDM callbacks. The callbacks registered will be posted back to | |
| 1266 // this thread via BindToCurrentLoop. | |
| 1267 | |
| 1268 // Since |this| holds a reference to the |cdm_|, by the time the CDM is | |
| 1269 // destructed, UnregisterPlayer() must have been called and |this| has been | |
| 1270 // destructed as well. So the |cdm_unset_cb| will never have a chance to be | |
| 1271 // called. | |
| 1272 // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms. | |
| 1273 cdm_registration_id_ = media_drm_bridge_cdm_context_->RegisterPlayer( | |
| 1274 media::BindToCurrentLoop( | |
| 1275 base::Bind(&AndroidVideoDecodeAccelerator::OnKeyAdded, | |
| 1276 weak_this_factory_.GetWeakPtr())), | |
| 1277 base::Bind(&base::DoNothing)); | |
| 1278 | |
| 1279 // Deferred initialization will continue in OnMediaCryptoReady(). | |
| 1280 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(media::BindToCurrentLoop( | |
| 1281 base::Bind(&AndroidVideoDecodeAccelerator::OnMediaCryptoReady, | |
| 1282 weak_this_factory_.GetWeakPtr()))); | |
| 1283 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | |
| 1284 } | |
| 1285 | |
| 1301 void AndroidVideoDecodeAccelerator::OnMediaCryptoReady( | 1286 void AndroidVideoDecodeAccelerator::OnMediaCryptoReady( |
| 1302 media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto, | 1287 media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto, |
| 1303 bool needs_protected_surface) { | 1288 bool needs_protected_surface) { |
| 1304 DVLOG(1) << __FUNCTION__; | 1289 DVLOG(1) << __FUNCTION__; |
| 1305 | 1290 |
| 1306 if (!media_crypto) { | 1291 if (!media_crypto) { |
| 1307 LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream."; | 1292 LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream."; |
| 1308 cdm_for_reference_holding_only_ = nullptr; | 1293 cdm_for_reference_holding_only_ = nullptr; |
| 1309 media_drm_bridge_cdm_context_ = nullptr; | 1294 media_drm_bridge_cdm_context_ = nullptr; |
| 1310 NotifyInitializationComplete(false); | 1295 NotifyInitializationComplete(false); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1462 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { | 1447 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { |
| 1463 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: | 1448 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: |
| 1464 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1449 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1465 } | 1450 } |
| 1466 } | 1451 } |
| 1467 | 1452 |
| 1468 return capabilities; | 1453 return capabilities; |
| 1469 } | 1454 } |
| 1470 | 1455 |
| 1471 } // namespace media | 1456 } // namespace media |
| OLD | NEW |