| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/filters/gpu_video_decoder.h" | 5 #include "media/filters/gpu_video_decoder.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <array> | 8 #include <array> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 | 114 |
| 115 GpuVideoDecoder::BufferData::~BufferData() {} | 115 GpuVideoDecoder::BufferData::~BufferData() {} |
| 116 | 116 |
| 117 GpuVideoDecoder::GpuVideoDecoder(GpuVideoAcceleratorFactories* factories, | 117 GpuVideoDecoder::GpuVideoDecoder(GpuVideoAcceleratorFactories* factories, |
| 118 const RequestSurfaceCB& request_surface_cb, | 118 const RequestSurfaceCB& request_surface_cb, |
| 119 scoped_refptr<MediaLog> media_log) | 119 scoped_refptr<MediaLog> media_log) |
| 120 : needs_bitstream_conversion_(false), | 120 : needs_bitstream_conversion_(false), |
| 121 factories_(factories), | 121 factories_(factories), |
| 122 request_surface_cb_(request_surface_cb), | 122 request_surface_cb_(request_surface_cb), |
| 123 media_log_(media_log), | 123 media_log_(media_log), |
| 124 vda_initialized_(false), |
| 124 state_(kNormal), | 125 state_(kNormal), |
| 125 decoder_texture_target_(0), | 126 decoder_texture_target_(0), |
| 126 pixel_format_(PIXEL_FORMAT_UNKNOWN), | 127 pixel_format_(PIXEL_FORMAT_UNKNOWN), |
| 127 next_picture_buffer_id_(0), | 128 next_picture_buffer_id_(0), |
| 128 next_bitstream_buffer_id_(0), | 129 next_bitstream_buffer_id_(0), |
| 129 available_pictures_(0), | 130 available_pictures_(0), |
| 130 needs_all_picture_buffers_to_decode_(false), | 131 needs_all_picture_buffers_to_decode_(false), |
| 131 supports_deferred_initialization_(false), | 132 supports_deferred_initialization_(false), |
| 132 requires_texture_copy_(false), | 133 requires_texture_copy_(false), |
| 133 cdm_id_(CdmContext::kInvalidCdmId), | 134 cdm_id_(CdmContext::kInvalidCdmId), |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 requires_restart_for_external_output_surface, | 321 requires_restart_for_external_output_surface, |
| 321 BindToCurrentLoop(base::Bind(&GpuVideoDecoder::OnSurfaceAvailable, | 322 BindToCurrentLoop(base::Bind(&GpuVideoDecoder::OnSurfaceAvailable, |
| 322 weak_factory_.GetWeakPtr()))); | 323 weak_factory_.GetWeakPtr()))); |
| 323 return; | 324 return; |
| 324 } | 325 } |
| 325 | 326 |
| 326 // If external surfaces are not supported we can complete initialization now. | 327 // If external surfaces are not supported we can complete initialization now. |
| 327 CompleteInitialization(SurfaceManager::kNoSurfaceID); | 328 CompleteInitialization(SurfaceManager::kNoSurfaceID); |
| 328 } | 329 } |
| 329 | 330 |
| 331 // OnSurfaceAvailable() might be called at any time between Initialize() and |
| 332 // ~GpuVideoDecoder() so we have to be careful to not make assumptions about |
| 333 // the current state. |
| 330 void GpuVideoDecoder::OnSurfaceAvailable(int surface_id) { | 334 void GpuVideoDecoder::OnSurfaceAvailable(int surface_id) { |
| 331 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 335 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 332 | 336 |
| 333 // It's possible for the vda to become null if NotifyError is called. | 337 if (!vda_) |
| 334 if (!vda_) { | 338 return; |
| 335 if (!init_cb_.is_null()) | 339 |
| 336 base::ResetAndReturn(&init_cb_).Run(false); | 340 // If the VDA has not been initialized, we were waiting for the first surface |
| 341 // so it can be passed to Initialize() via the config. We can't call |
| 342 // SetSurface() before initializing because there is no remote VDA to handle |
| 343 // the call yet. |
| 344 if (!vda_initialized_) { |
| 345 CompleteInitialization(surface_id); |
| 337 return; | 346 return; |
| 338 } | 347 } |
| 339 | 348 |
| 340 // If initialization has already completed, there's nothing to do but try to | 349 // The VDA must be already initialized (or async initialization is in |
| 341 // set the surface. If we're still initializing, we must pass the surface via | 350 // progress) so we can call SetSurface(). |
| 342 // the config since the remote VDA has not yet been created. | 351 vda_->SetSurface(surface_id); |
| 343 if (init_cb_.is_null()) { | |
| 344 vda_->SetSurface(surface_id); | |
| 345 return; | |
| 346 } | |
| 347 | |
| 348 // Otherwise initialization was waiting for the surface, so complete it now. | |
| 349 CompleteInitialization(surface_id); | |
| 350 } | 352 } |
| 351 | 353 |
| 352 void GpuVideoDecoder::CompleteInitialization(int surface_id) { | 354 void GpuVideoDecoder::CompleteInitialization(int surface_id) { |
| 353 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 355 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 354 DCHECK(vda_); | 356 DCHECK(vda_); |
| 355 DCHECK(!init_cb_.is_null()); | 357 DCHECK(!init_cb_.is_null()); |
| 358 DCHECK(!vda_initialized_); |
| 356 | 359 |
| 357 VideoDecodeAccelerator::Config vda_config; | 360 VideoDecodeAccelerator::Config vda_config; |
| 358 vda_config.profile = config_.profile(); | 361 vda_config.profile = config_.profile(); |
| 359 vda_config.cdm_id = cdm_id_; | 362 vda_config.cdm_id = cdm_id_; |
| 360 vda_config.surface_id = surface_id; | 363 vda_config.surface_id = surface_id; |
| 361 vda_config.encryption_scheme = config_.encryption_scheme(); | 364 vda_config.encryption_scheme = config_.encryption_scheme(); |
| 362 vda_config.is_deferred_initialization_allowed = true; | 365 vda_config.is_deferred_initialization_allowed = true; |
| 363 vda_config.initial_expected_coded_size = config_.coded_size(); | 366 vda_config.initial_expected_coded_size = config_.coded_size(); |
| 364 | 367 |
| 365 #if defined(OS_ANDROID) && defined(USE_PROPRIETARY_CODECS) | 368 #if defined(OS_ANDROID) && defined(USE_PROPRIETARY_CODECS) |
| 366 // We pass the SPS and PPS on Android because it lets us initialize | 369 // We pass the SPS and PPS on Android because it lets us initialize |
| 367 // MediaCodec more reliably (http://crbug.com/649185). | 370 // MediaCodec more reliably (http://crbug.com/649185). |
| 368 if (config_.codec() == kCodecH264) | 371 if (config_.codec() == kCodecH264) |
| 369 ExtractSpsAndPps(config_.extra_data(), &vda_config.sps, &vda_config.pps); | 372 ExtractSpsAndPps(config_.extra_data(), &vda_config.sps, &vda_config.pps); |
| 370 #endif | 373 #endif |
| 371 | 374 |
| 375 vda_initialized_ = true; |
| 372 if (!vda_->Initialize(vda_config, this)) { | 376 if (!vda_->Initialize(vda_config, this)) { |
| 373 DVLOG(1) << "VDA::Initialize failed."; | 377 DVLOG(1) << "VDA::Initialize failed."; |
| 378 // It's important to set |vda_| to null so that OnSurfaceAvailable() will |
| 379 // not call SetSurface() on a nonexistent remote VDA. |
| 380 DestroyVDA(); |
| 374 base::ResetAndReturn(&init_cb_).Run(false); | 381 base::ResetAndReturn(&init_cb_).Run(false); |
| 375 return; | 382 return; |
| 376 } | 383 } |
| 377 | 384 |
| 378 // If deferred initialization is not supported, initialization is complete. | 385 // If deferred initialization is not supported, initialization is complete. |
| 379 // Otherwise, a call to NotifyInitializationComplete will follow with the | 386 // Otherwise, a call to NotifyInitializationComplete will follow with the |
| 380 // result of deferred initialization. | 387 // result of deferred initialization. |
| 381 if (!supports_deferred_initialization_) | 388 if (!supports_deferred_initialization_) |
| 382 base::ResetAndReturn(&init_cb_).Run(true); | 389 base::ResetAndReturn(&init_cb_).Run(true); |
| 383 } | 390 } |
| 384 | 391 |
| 385 void GpuVideoDecoder::NotifyInitializationComplete(bool success) { | 392 void GpuVideoDecoder::NotifyInitializationComplete(bool success) { |
| 386 DVLOG_IF(1, !success) << __func__ << " Deferred initialization failed."; | 393 DVLOG_IF(1, !success) << __func__ << " Deferred initialization failed."; |
| 387 DCHECK(!init_cb_.is_null()); | |
| 388 | 394 |
| 389 base::ResetAndReturn(&init_cb_).Run(success); | 395 if (init_cb_) |
| 396 base::ResetAndReturn(&init_cb_).Run(success); |
| 390 } | 397 } |
| 391 | 398 |
| 392 void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) { | 399 void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) { |
| 393 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 400 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 394 for (const auto& kv : *buffers) { | 401 for (const auto& kv : *buffers) { |
| 395 for (uint32_t id : kv.second.client_texture_ids()) | 402 for (uint32_t id : kv.second.client_texture_ids()) |
| 396 factories_->DeleteTexture(id); | 403 factories_->DeleteTexture(id); |
| 397 } | 404 } |
| 398 | 405 |
| 399 buffers->clear(); | 406 buffers->clear(); |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 | 861 |
| 855 if (!pending_reset_cb_.is_null()) | 862 if (!pending_reset_cb_.is_null()) |
| 856 base::ResetAndReturn(&pending_reset_cb_).Run(); | 863 base::ResetAndReturn(&pending_reset_cb_).Run(); |
| 857 } | 864 } |
| 858 | 865 |
| 859 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { | 866 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { |
| 860 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); | 867 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); |
| 861 if (!vda_) | 868 if (!vda_) |
| 862 return; | 869 return; |
| 863 | 870 |
| 871 if (init_cb_) |
| 872 base::ResetAndReturn(&init_cb_).Run(false); |
| 873 |
| 864 // If we have any bitstream buffers, then notify one that an error has | 874 // If we have any bitstream buffers, then notify one that an error has |
| 865 // occurred. This guarantees that somebody finds out about the error. If | 875 // occurred. This guarantees that somebody finds out about the error. If |
| 866 // we don't do this, and if the max decodes are already in flight, then there | 876 // we don't do this, and if the max decodes are already in flight, then there |
| 867 // won't be another decode request to report the error. | 877 // won't be another decode request to report the error. |
| 868 if (!bitstream_buffers_in_decoder_.empty()) { | 878 if (!bitstream_buffers_in_decoder_.empty()) { |
| 869 auto it = bitstream_buffers_in_decoder_.begin(); | 879 auto it = bitstream_buffers_in_decoder_.begin(); |
| 870 it->second.done_cb.Run(DecodeStatus::DECODE_ERROR); | 880 it->second.done_cb.Run(DecodeStatus::DECODE_ERROR); |
| 871 bitstream_buffers_in_decoder_.erase(it); | 881 bitstream_buffers_in_decoder_.erase(it); |
| 872 } | 882 } |
| 873 | 883 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 901 } | 911 } |
| 902 return false; | 912 return false; |
| 903 } | 913 } |
| 904 | 914 |
| 905 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() | 915 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() |
| 906 const { | 916 const { |
| 907 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); | 917 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); |
| 908 } | 918 } |
| 909 | 919 |
| 910 } // namespace media | 920 } // namespace media |
| OLD | NEW |