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

Side by Side Diff: media/filters/gpu_video_decoder.cc

Issue 2621153004: media: Fix a GpuVideoDecoder initialization crash on Android (Closed)
Patch Set: Created 3 years, 11 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
OLDNEW
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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 return; 323 return;
324 } 324 }
325 325
326 // If external surfaces are not supported we can complete initialization now. 326 // If external surfaces are not supported we can complete initialization now.
327 CompleteInitialization(SurfaceManager::kNoSurfaceID); 327 CompleteInitialization(SurfaceManager::kNoSurfaceID);
328 } 328 }
329 329
330 void GpuVideoDecoder::OnSurfaceAvailable(int surface_id) { 330 void GpuVideoDecoder::OnSurfaceAvailable(int surface_id) {
331 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 331 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
332 332
333 // It's possible for the vda to become null if NotifyError is called. 333 if (!vda_)
334 if (!vda_) { 334 return;
335 if (!init_cb_.is_null()) 335
336 base::ResetAndReturn(&init_cb_).Run(false); 336 // If the VDA has not been initialized, we were waiting for the first surface
337 // so it can be passed to Initialize() via the config. We can't call
338 // SetSurface() before initializing because there is no remote VDA to handle
339 // the call yet.
340 if (!vda_initialized_) {
341 CompleteInitialization(surface_id);
337 return; 342 return;
338 } 343 }
339 344
340 // If initialization has already completed, there's nothing to do but try to 345 // 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 346 // progress) so we can call SetSurface().
342 // the config since the remote VDA has not yet been created. 347 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 } 348 }
351 349
352 void GpuVideoDecoder::CompleteInitialization(int surface_id) { 350 void GpuVideoDecoder::CompleteInitialization(int surface_id) {
353 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 351 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
354 DCHECK(vda_); 352 DCHECK(vda_);
355 DCHECK(!init_cb_.is_null()); 353 DCHECK(!init_cb_.is_null());
354 DCHECK(!vda_initialized_);
356 355
357 VideoDecodeAccelerator::Config vda_config; 356 VideoDecodeAccelerator::Config vda_config;
358 vda_config.profile = config_.profile(); 357 vda_config.profile = config_.profile();
359 vda_config.cdm_id = cdm_id_; 358 vda_config.cdm_id = cdm_id_;
360 vda_config.surface_id = surface_id; 359 vda_config.surface_id = surface_id;
361 vda_config.encryption_scheme = config_.encryption_scheme(); 360 vda_config.encryption_scheme = config_.encryption_scheme();
362 vda_config.is_deferred_initialization_allowed = true; 361 vda_config.is_deferred_initialization_allowed = true;
363 vda_config.initial_expected_coded_size = config_.coded_size(); 362 vda_config.initial_expected_coded_size = config_.coded_size();
364 363
365 #if defined(OS_ANDROID) && defined(USE_PROPRIETARY_CODECS) 364 #if defined(OS_ANDROID) && defined(USE_PROPRIETARY_CODECS)
366 // We pass the SPS and PPS on Android because it lets us initialize 365 // We pass the SPS and PPS on Android because it lets us initialize
367 // MediaCodec more reliably (http://crbug.com/649185). 366 // MediaCodec more reliably (http://crbug.com/649185).
368 if (config_.codec() == kCodecH264) 367 if (config_.codec() == kCodecH264)
369 ExtractSpsAndPps(config_.extra_data(), &vda_config.sps, &vda_config.pps); 368 ExtractSpsAndPps(config_.extra_data(), &vda_config.sps, &vda_config.pps);
370 #endif 369 #endif
371 370
371 vda_initialized_ = true;
372 if (!vda_->Initialize(vda_config, this)) { 372 if (!vda_->Initialize(vda_config, this)) {
373 DVLOG(1) << "VDA::Initialize failed."; 373 DVLOG(1) << "VDA::Initialize failed.";
374 // It's important to set |vda_| to null so that OnSurfaceAvailable() will
375 // not call SetSurface() on a nonexistent remote VDA.
376 DestroyVDA();
374 base::ResetAndReturn(&init_cb_).Run(false); 377 base::ResetAndReturn(&init_cb_).Run(false);
375 return; 378 return;
376 } 379 }
377 380
378 // If deferred initialization is not supported, initialization is complete. 381 // If deferred initialization is not supported, initialization is complete.
379 // Otherwise, a call to NotifyInitializationComplete will follow with the 382 // Otherwise, a call to NotifyInitializationComplete will follow with the
380 // result of deferred initialization. 383 // result of deferred initialization.
381 if (!supports_deferred_initialization_) 384 if (!supports_deferred_initialization_)
382 base::ResetAndReturn(&init_cb_).Run(true); 385 base::ResetAndReturn(&init_cb_).Run(true);
383 } 386 }
384 387
385 void GpuVideoDecoder::NotifyInitializationComplete(bool success) { 388 void GpuVideoDecoder::NotifyInitializationComplete(bool success) {
386 DVLOG_IF(1, !success) << __func__ << " Deferred initialization failed."; 389 DVLOG_IF(1, !success) << __func__ << " Deferred initialization failed.";
387 DCHECK(!init_cb_.is_null());
388 390
389 base::ResetAndReturn(&init_cb_).Run(success); 391 if (init_cb_)
392 base::ResetAndReturn(&init_cb_).Run(success);
390 } 393 }
391 394
392 void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) { 395 void GpuVideoDecoder::DestroyPictureBuffers(PictureBufferMap* buffers) {
393 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 396 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
394 for (const auto& kv : *buffers) { 397 for (const auto& kv : *buffers) {
395 for (uint32_t id : kv.second.client_texture_ids()) 398 for (uint32_t id : kv.second.client_texture_ids())
396 factories_->DeleteTexture(id); 399 factories_->DeleteTexture(id);
397 } 400 }
398 401
399 buffers->clear(); 402 buffers->clear();
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 857
855 if (!pending_reset_cb_.is_null()) 858 if (!pending_reset_cb_.is_null())
856 base::ResetAndReturn(&pending_reset_cb_).Run(); 859 base::ResetAndReturn(&pending_reset_cb_).Run();
857 } 860 }
858 861
859 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) { 862 void GpuVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
860 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); 863 DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
861 if (!vda_) 864 if (!vda_)
862 return; 865 return;
863 866
867 if (init_cb_)
868 base::ResetAndReturn(&init_cb_).Run(false);
869
864 // If we have any bitstream buffers, then notify one that an error has 870 // 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 871 // 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 872 // 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. 873 // won't be another decode request to report the error.
868 if (!bitstream_buffers_in_decoder_.empty()) { 874 if (!bitstream_buffers_in_decoder_.empty()) {
869 auto it = bitstream_buffers_in_decoder_.begin(); 875 auto it = bitstream_buffers_in_decoder_.begin();
870 it->second.done_cb.Run(DecodeStatus::DECODE_ERROR); 876 it->second.done_cb.Run(DecodeStatus::DECODE_ERROR);
871 bitstream_buffers_in_decoder_.erase(it); 877 bitstream_buffers_in_decoder_.erase(it);
872 } 878 }
873 879
(...skipping 27 matching lines...) Expand all
901 } 907 }
902 return false; 908 return false;
903 } 909 }
904 910
905 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() 911 void GpuVideoDecoder::DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent()
906 const { 912 const {
907 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread()); 913 DCHECK(factories_->GetTaskRunner()->BelongsToCurrentThread());
908 } 914 }
909 915
910 } // namespace media 916 } // namespace media
OLDNEW
« media/filters/gpu_video_decoder.h ('K') | « media/filters/gpu_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698