| 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 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 if (!media_drm_bridge_cdm_context_) | 329 if (!media_drm_bridge_cdm_context_) |
| 330 return; | 330 return; |
| 331 | 331 |
| 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 DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString(); |
| 340 TRACE_EVENT0("media", "AVDA::Initialize"); |
| 339 DCHECK(!media_codec_); | 341 DCHECK(!media_codec_); |
| 340 DCHECK(thread_checker_.CalledOnValidThread()); | 342 DCHECK(thread_checker_.CalledOnValidThread()); |
| 341 TRACE_EVENT0("media", "AVDA::Initialize"); | |
| 342 | |
| 343 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 DLOG(ERROR) << "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 DLOG(ERROR) << "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 |
| 371 if (!profile_supported) { | 366 if (is_encrypted_ && !deferred_initialization_pending_) { |
| 367 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams"; |
| 368 return false; |
| 369 } |
| 370 |
| 371 if (codec_config_->codec_ != media::kCodecVP8 && |
| 372 codec_config_->codec_ != media::kCodecVP9 && |
| 373 codec_config_->codec_ != media::kCodecH264) { |
| 372 LOG(ERROR) << "Unsupported profile: " << config.profile; | 374 LOG(ERROR) << "Unsupported profile: " << config.profile; |
| 373 return false; | 375 return false; |
| 374 } | 376 } |
| 375 | 377 |
| 376 // For encrypted streams we postpone configuration until MediaCrypto is | |
| 377 // available. | |
| 378 DCHECK(!is_encrypted_ || deferred_initialization_pending_); | |
| 379 | |
| 380 // Only use MediaCodec for VP8/9 if it's likely backed by hardware | 378 // Only use MediaCodec for VP8/9 if it's likely backed by hardware |
| 381 // or if the stream is encrypted. | 379 // or if the stream is encrypted. |
| 382 if ((codec_config_->codec_ == media::kCodecVP8 || | 380 if ((codec_config_->codec_ == media::kCodecVP8 || |
| 383 codec_config_->codec_ == media::kCodecVP9) && | 381 codec_config_->codec_ == media::kCodecVP9) && |
| 384 !is_encrypted_ && | 382 !is_encrypted_ && |
| 385 media::VideoCodecBridge::IsKnownUnaccelerated( | 383 media::VideoCodecBridge::IsKnownUnaccelerated( |
| 386 codec_config_->codec_, media::MEDIA_CODEC_DECODER)) { | 384 codec_config_->codec_, media::MEDIA_CODEC_DECODER)) { |
| 387 DVLOG(1) << "Initialization failed: " | 385 DVLOG(1) << "Initialization failed: " |
| 388 << (codec_config_->codec_ == media::kCodecVP8 ? "vp8" : "vp9") | 386 << (codec_config_->codec_ == media::kCodecVP8 ? "vp8" : "vp9") |
| 389 << " is not hardware accelerated"; | 387 << " is not hardware accelerated"; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 scoped_refptr<gfx::SurfaceTexture> surface_texture = | 424 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
| 427 strategy_->GetSurfaceTexture(); | 425 strategy_->GetSurfaceTexture(); |
| 428 if (surface_texture) { | 426 if (surface_texture) { |
| 429 on_frame_available_handler_ = | 427 on_frame_available_handler_ = |
| 430 new OnFrameAvailableHandler(this, surface_texture); | 428 new OnFrameAvailableHandler(this, surface_texture); |
| 431 } | 429 } |
| 432 | 430 |
| 433 // Start the thread for async configuration, even if we don't need it now. | 431 // Start the thread for async configuration, even if we don't need it now. |
| 434 // ResetCodecState might rebuild the codec later, for example. | 432 // ResetCodecState might rebuild the codec later, for example. |
| 435 if (!g_avda_timer.Pointer()->StartThread(this)) { | 433 if (!g_avda_timer.Pointer()->StartThread(this)) { |
| 436 LOG(ERROR) << "Failed to start thread for AVDA timer"; | 434 LOG(ERROR) << "Failed to start AVDA thread"; |
| 437 return false; | 435 return false; |
| 438 } | 436 } |
| 439 | 437 |
| 440 // If we are encrypted, then we aren't able to create the codec yet. | 438 // If we are encrypted, then we aren't able to create the codec yet. |
| 441 if (is_encrypted_) | 439 if (is_encrypted_) { |
| 440 InitializeCdm(config.cdm_id); |
| 442 return true; | 441 return true; |
| 442 } |
| 443 | 443 |
| 444 if (deferred_initialization_pending_) { | 444 if (deferred_initialization_pending_) { |
| 445 ConfigureMediaCodecAsynchronously(); | 445 ConfigureMediaCodecAsynchronously(); |
| 446 return true; | 446 return true; |
| 447 } | 447 } |
| 448 | 448 |
| 449 // If the client doesn't support deferred initialization (WebRTC), then we | 449 // If the client doesn't support deferred initialization (WebRTC), then we |
| 450 // should complete it now and return a meaningful result. | 450 // should complete it now and return a meaningful result. |
| 451 return ConfigureMediaCodecSynchronously(); | 451 return ConfigureMediaCodecSynchronously(); |
| 452 } | 452 } |
| 453 | 453 |
| 454 void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) { | |
| 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) { | 454 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { |
| 504 DCHECK(thread_checker_.CalledOnValidThread()); | 455 DCHECK(thread_checker_.CalledOnValidThread()); |
| 505 TRACE_EVENT0("media", "AVDA::DoIOTask"); | 456 TRACE_EVENT0("media", "AVDA::DoIOTask"); |
| 506 if (state_ == ERROR || state_ == WAITING_FOR_CODEC) | 457 if (state_ == ERROR || state_ == WAITING_FOR_CODEC) |
| 507 return; | 458 return; |
| 508 | 459 |
| 509 strategy_->MaybeRenderEarly(); | 460 strategy_->MaybeRenderEarly(); |
| 510 bool did_work = false, did_input = false, did_output = false; | 461 bool did_work = false, did_input = false, did_output = false; |
| 511 do { | 462 do { |
| 512 did_input = QueueInput(); | 463 did_input = QueueInput(); |
| (...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1291 const ::tracked_objects::Location& from_here, | 1242 const ::tracked_objects::Location& from_here, |
| 1292 media::VideoDecodeAccelerator::Error error) { | 1243 media::VideoDecodeAccelerator::Error error) { |
| 1293 base::MessageLoop::current()->PostDelayedTask( | 1244 base::MessageLoop::current()->PostDelayedTask( |
| 1294 from_here, | 1245 from_here, |
| 1295 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, | 1246 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, |
| 1296 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), | 1247 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), |
| 1297 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); | 1248 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); |
| 1298 state_ = ERROR; | 1249 state_ = ERROR; |
| 1299 } | 1250 } |
| 1300 | 1251 |
| 1252 void AndroidVideoDecodeAccelerator::InitializeCdm(int cdm_id) { |
| 1253 DVLOG(2) << __FUNCTION__ << ": " << cdm_id; |
| 1254 |
| 1255 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 1256 NOTIMPLEMENTED(); |
| 1257 NotifyInitializationComplete(false); |
| 1258 #else |
| 1259 // Store the CDM to hold a reference to it. |
| 1260 cdm_for_reference_holding_only_ = media::MojoCdmService::LegacyGetCdm(cdm_id); |
| 1261 DCHECK(cdm_for_reference_holding_only_); |
| 1262 |
| 1263 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext. |
| 1264 media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>( |
| 1265 cdm_for_reference_holding_only_->GetCdmContext()); |
| 1266 DCHECK(media_drm_bridge_cdm_context_); |
| 1267 |
| 1268 // Register CDM callbacks. The callbacks registered will be posted back to |
| 1269 // this thread via BindToCurrentLoop. |
| 1270 |
| 1271 // Since |this| holds a reference to the |cdm_|, by the time the CDM is |
| 1272 // destructed, UnregisterPlayer() must have been called and |this| has been |
| 1273 // destructed as well. So the |cdm_unset_cb| will never have a chance to be |
| 1274 // called. |
| 1275 // TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms. |
| 1276 cdm_registration_id_ = media_drm_bridge_cdm_context_->RegisterPlayer( |
| 1277 media::BindToCurrentLoop( |
| 1278 base::Bind(&AndroidVideoDecodeAccelerator::OnKeyAdded, |
| 1279 weak_this_factory_.GetWeakPtr())), |
| 1280 base::Bind(&base::DoNothing)); |
| 1281 |
| 1282 // Deferred initialization will continue in OnMediaCryptoReady(). |
| 1283 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(media::BindToCurrentLoop( |
| 1284 base::Bind(&AndroidVideoDecodeAccelerator::OnMediaCryptoReady, |
| 1285 weak_this_factory_.GetWeakPtr()))); |
| 1286 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 1287 } |
| 1288 |
| 1301 void AndroidVideoDecodeAccelerator::OnMediaCryptoReady( | 1289 void AndroidVideoDecodeAccelerator::OnMediaCryptoReady( |
| 1302 media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto, | 1290 media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto, |
| 1303 bool needs_protected_surface) { | 1291 bool needs_protected_surface) { |
| 1304 DVLOG(1) << __FUNCTION__; | 1292 DVLOG(1) << __FUNCTION__; |
| 1305 | 1293 |
| 1306 if (!media_crypto) { | 1294 if (!media_crypto) { |
| 1307 LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream."; | 1295 LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream."; |
| 1308 cdm_for_reference_holding_only_ = nullptr; | 1296 cdm_for_reference_holding_only_ = nullptr; |
| 1309 media_drm_bridge_cdm_context_ = nullptr; | 1297 media_drm_bridge_cdm_context_ = nullptr; |
| 1310 NotifyInitializationComplete(false); | 1298 NotifyInitializationComplete(false); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1462 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { | 1450 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { |
| 1463 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: | 1451 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: |
| 1464 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1452 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1465 } | 1453 } |
| 1466 } | 1454 } |
| 1467 | 1455 |
| 1468 return capabilities; | 1456 return capabilities; |
| 1469 } | 1457 } |
| 1470 | 1458 |
| 1471 } // namespace media | 1459 } // namespace media |
| OLD | NEW |