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

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

Issue 2621153004: media: Fix a GpuVideoDecoder initialization crash on Android (Closed)
Patch Set: bless windows for initializing this with garbage 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
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « media/filters/gpu_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698