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

Side by Side Diff: media/gpu/android_video_decode_accelerator.cc

Issue 2507463004: Fix broken SurfaceView usage on < M devices. (Closed)
Patch Set: Created 4 years, 1 month 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) 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 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 state_(NO_ERROR), 304 state_(NO_ERROR),
305 picturebuffers_requested_(false), 305 picturebuffers_requested_(false),
306 picture_buffer_manager_(this), 306 picture_buffer_manager_(this),
307 drain_type_(DRAIN_TYPE_NONE), 307 drain_type_(DRAIN_TYPE_NONE),
308 media_drm_bridge_cdm_context_(nullptr), 308 media_drm_bridge_cdm_context_(nullptr),
309 cdm_registration_id_(0), 309 cdm_registration_id_(0),
310 pending_input_buf_index_(-1), 310 pending_input_buf_index_(-1),
311 deferred_initialization_pending_(false), 311 deferred_initialization_pending_(false),
312 codec_needs_reset_(false), 312 codec_needs_reset_(false),
313 defer_surface_creation_(false), 313 defer_surface_creation_(false),
314 surface_id_(SurfaceManager::kNoSurfaceID),
315 weak_this_factory_(this) {} 314 weak_this_factory_(this) {}
316 315
317 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 316 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
318 DCHECK(thread_checker_.CalledOnValidThread()); 317 DCHECK(thread_checker_.CalledOnValidThread());
319 g_avda_manager.Get().StopTimer(this); 318 g_avda_manager.Get().StopTimer(this);
320 g_avda_codec_allocator.Get().StopThread(this); 319 g_avda_codec_allocator.Get().StopThread(this);
321 320
322 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 321 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
323 if (!media_drm_bridge_cdm_context_) 322 if (!media_drm_bridge_cdm_context_)
324 return; 323 return;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 << " is not hardware accelerated"; 382 << " is not hardware accelerated";
384 return false; 383 return false;
385 } 384 }
386 385
387 auto gles_decoder = get_gles2_decoder_cb_.Run(); 386 auto gles_decoder = get_gles2_decoder_cb_.Run();
388 if (!gles_decoder) { 387 if (!gles_decoder) {
389 DLOG(ERROR) << "Failed to get gles2 decoder instance."; 388 DLOG(ERROR) << "Failed to get gles2 decoder instance.";
390 return false; 389 return false;
391 } 390 }
392 391
393 // If SetSurface() was called before initialize, pick up the surface. 392 // SetSurface() can't be called before Initialize(), so we pick up our first
394 if (pending_surface_id_) { 393 // surface ID from the codec configuration.
395 surface_id_ = pending_surface_id_.value(); 394 DCHECK(!pending_surface_id_);
dcheng 2016/11/16 00:58:45 This isn't a new issue, but it makes me concerned
DaleCurtis 2016/11/16 01:04:29 pending_surface_id_ is a base::Optional() so this
396 pending_surface_id_.reset();
397 }
398 395
399 // If we're low on resources, we may decide to defer creation of the surface 396 // If we're low on resources, we may decide to defer creation of the surface
400 // until the codec is actually used. 397 // until the codec is actually used.
401 if (g_avda_manager.Get().ShouldDeferSurfaceCreation(surface_id_, 398 if (g_avda_manager.Get().ShouldDeferSurfaceCreation(config_.surface_id,
402 codec_config_->codec_)) { 399 codec_config_->codec_)) {
403 DCHECK(!deferred_initialization_pending_); 400 DCHECK(!deferred_initialization_pending_);
404 401
405 // We should never be here if a SurfaceView is required. 402 // We should never be here if a SurfaceView is required.
406 DCHECK_EQ(surface_id_, SurfaceManager::kNoSurfaceID); 403 DCHECK_EQ(config_.surface_id, SurfaceManager::kNoSurfaceID);
407 DCHECK(g_avda_manager.Get().AllocateSurface(surface_id_, this)); 404 DCHECK(g_avda_manager.Get().AllocateSurface(config_.surface_id, this));
dcheng 2016/11/16 00:58:45 Why do we call this in a DCHECK()? Isn't it a no-o
DaleCurtis 2016/11/16 01:04:29 It is with the current code, it's prevention again
dcheng 2016/11/16 01:06:33 It seems weird to call something called AllocateX
DaleCurtis 2016/11/16 01:16:15 Will leave for now and let watk@ remove with upcom
408 405
409 defer_surface_creation_ = true; 406 defer_surface_creation_ = true;
410 NotifyInitializationComplete(true); 407 NotifyInitializationComplete(true);
411 return true; 408 return true;
412 } 409 }
413 410
414 // We signaled that we support deferred initialization, so see if the client 411 // We signaled that we support deferred initialization, so see if the client
415 // does also. 412 // does also.
416 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; 413 deferred_initialization_pending_ = config.is_deferred_initialization_allowed;
417 if (config_.is_encrypted && !deferred_initialization_pending_) { 414 if (config_.is_encrypted && !deferred_initialization_pending_) {
418 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams"; 415 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams";
419 return false; 416 return false;
420 } 417 }
421 418
422 if (g_avda_manager.Get().AllocateSurface(surface_id_, this)) { 419 if (g_avda_manager.Get().AllocateSurface(config_.surface_id, this)) {
423 // We have successfully owned the surface, so finish initialization now. 420 // We have successfully owned the surface, so finish initialization now.
424 return InitializePictureBufferManager(); 421 return InitializePictureBufferManager();
425 } 422 }
426 423
427 // We have to wait for some other AVDA instance to free up the surface. 424 // We have to wait for some other AVDA instance to free up the surface.
428 // OnSurfaceAvailable will be called when it's available. 425 // OnSurfaceAvailable will be called when it's available.
429 return true; 426 return true;
430 } 427 }
431 428
432 void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) { 429 void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) {
433 DCHECK(deferred_initialization_pending_); 430 DCHECK(deferred_initialization_pending_);
434 DCHECK(!defer_surface_creation_); 431 DCHECK(!defer_surface_creation_);
435 432
436 if (!success || !InitializePictureBufferManager()) { 433 if (!success || !InitializePictureBufferManager()) {
437 NotifyInitializationComplete(false); 434 NotifyInitializationComplete(false);
438 deferred_initialization_pending_ = false; 435 deferred_initialization_pending_ = false;
439 } 436 }
440 } 437 }
441 438
442 bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() { 439 bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() {
443 if (!make_context_current_cb_.Run()) { 440 if (!make_context_current_cb_.Run()) {
444 LOG(ERROR) << "Failed to make this decoder's GL context current."; 441 LOG(ERROR) << "Failed to make this decoder's GL context current.";
445 return false; 442 return false;
446 } 443 }
447 444
448 codec_config_->surface_ = picture_buffer_manager_.Initialize(surface_id_); 445 codec_config_->surface_ =
446 picture_buffer_manager_.Initialize(config_.surface_id);
449 if (codec_config_->surface_.IsEmpty()) 447 if (codec_config_->surface_.IsEmpty())
450 return false; 448 return false;
451 449
452 on_destroying_surface_cb_ = 450 on_destroying_surface_cb_ =
453 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface, 451 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface,
454 weak_this_factory_.GetWeakPtr()); 452 weak_this_factory_.GetWeakPtr());
455 AVDASurfaceTracker::GetInstance()->RegisterOnDestroyingSurfaceCallback( 453 AVDASurfaceTracker::GetInstance()->RegisterOnDestroyingSurfaceCallback(
456 on_destroying_surface_cb_); 454 on_destroying_surface_cb_);
457 455
458 if (!g_avda_codec_allocator.Get().StartThread(this)) 456 if (!g_avda_codec_allocator.Get().StartThread(this))
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 StartCodecDrain(DRAIN_FOR_RESET); 1226 StartCodecDrain(DRAIN_FOR_RESET);
1229 } else { 1227 } else {
1230 ResetCodecState(); 1228 ResetCodecState();
1231 base::ThreadTaskRunnerHandle::Get()->PostTask( 1229 base::ThreadTaskRunnerHandle::Get()->PostTask(
1232 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, 1230 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone,
1233 weak_this_factory_.GetWeakPtr())); 1231 weak_this_factory_.GetWeakPtr()));
1234 } 1232 }
1235 } 1233 }
1236 1234
1237 void AndroidVideoDecodeAccelerator::SetSurface(int32_t surface_id) { 1235 void AndroidVideoDecodeAccelerator::SetSurface(int32_t surface_id) {
1238 if (surface_id == surface_id_) { 1236 if (surface_id == config_.surface_id) {
1239 pending_surface_id_.reset(); 1237 pending_surface_id_.reset();
1240 return; 1238 return;
1241 } 1239 }
1242 1240
1243 // Surface changes never take effect immediately, they will be handled during 1241 // Surface changes never take effect immediately, they will be handled during
1244 // DequeOutput() once we get to a good switch point or immediately during an 1242 // DequeOutput() once we get to a good switch point or immediately during an
1245 // OnDestroyingSurface() call. 1243 // OnDestroyingSurface() call.
1246 pending_surface_id_ = surface_id; 1244 pending_surface_id_ = surface_id;
1247 } 1245 }
1248 1246
(...skipping 23 matching lines...) Expand all
1272 DVLOG(1) << __FUNCTION__; 1270 DVLOG(1) << __FUNCTION__;
1273 DCHECK(thread_checker_.CalledOnValidThread()); 1271 DCHECK(thread_checker_.CalledOnValidThread());
1274 1272
1275 if (!on_destroying_surface_cb_.is_null()) { 1273 if (!on_destroying_surface_cb_.is_null()) {
1276 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback( 1274 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback(
1277 on_destroying_surface_cb_); 1275 on_destroying_surface_cb_);
1278 } 1276 }
1279 1277
1280 // We no longer care about |surface_id|, in case we did before. It's okay 1278 // We no longer care about |surface_id|, in case we did before. It's okay
1281 // if we have no surface and/or weren't the owner or a waiter. 1279 // if we have no surface and/or weren't the owner or a waiter.
1282 g_avda_manager.Get().DeallocateSurface(surface_id_, this); 1280 g_avda_manager.Get().DeallocateSurface(config_.surface_id, this);
1283 1281
1284 // Note that async codec construction might still be in progress. In that 1282 // Note that async codec construction might still be in progress. In that
1285 // case, the codec will be deleted when it completes once we invalidate all 1283 // case, the codec will be deleted when it completes once we invalidate all
1286 // our weak refs. 1284 // our weak refs.
1287 weak_this_factory_.InvalidateWeakPtrs(); 1285 weak_this_factory_.InvalidateWeakPtrs();
1288 if (media_codec_) { 1286 if (media_codec_) {
1289 g_avda_manager.Get().StopTimer(this); 1287 g_avda_manager.Get().StopTimer(this);
1290 ReleaseMediaCodec(); 1288 ReleaseMediaCodec();
1291 } 1289 }
1292 1290
(...skipping 13 matching lines...) Expand all
1306 base::WeakPtr<gpu::gles2::GLES2Decoder> 1304 base::WeakPtr<gpu::gles2::GLES2Decoder>
1307 AndroidVideoDecodeAccelerator::GetGlDecoder() const { 1305 AndroidVideoDecodeAccelerator::GetGlDecoder() const {
1308 return get_gles2_decoder_cb_.Run(); 1306 return get_gles2_decoder_cb_.Run();
1309 } 1307 }
1310 1308
1311 void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) { 1309 void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) {
1312 DCHECK(thread_checker_.CalledOnValidThread()); 1310 DCHECK(thread_checker_.CalledOnValidThread());
1313 TRACE_EVENT0("media", "AVDA::OnDestroyingSurface"); 1311 TRACE_EVENT0("media", "AVDA::OnDestroyingSurface");
1314 DVLOG(1) << __FUNCTION__ << " surface_id: " << surface_id; 1312 DVLOG(1) << __FUNCTION__ << " surface_id: " << surface_id;
1315 1313
1316 if (surface_id != surface_id_) 1314 if (surface_id != config_.surface_id)
1317 return; 1315 return;
1318 1316
1319 // If the API is available avoid having to restart the decoder in order to 1317 // If the API is available avoid having to restart the decoder in order to
1320 // leave fullscreen. If we don't clear the surface immediately during this 1318 // leave fullscreen. If we don't clear the surface immediately during this
1321 // callback, the MediaCodec will throw an error as the surface is destroyed. 1319 // callback, the MediaCodec will throw an error as the surface is destroyed.
1322 if (base::android::BuildInfo::GetInstance()->sdk_int() >= 23) { 1320 if (base::android::BuildInfo::GetInstance()->sdk_int() >= 23) {
1323 // Since we can't wait for a transition, we must invalidate all outstanding 1321 // Since we can't wait for a transition, we must invalidate all outstanding
1324 // picture buffers to avoid putting the GL system in a broken state. 1322 // picture buffers to avoid putting the GL system in a broken state.
1325 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_); 1323 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_);
1326 1324
1327 // Switch away from the surface being destroyed to a surface texture. 1325 // Switch away from the surface being destroyed to a surface texture.
1328 DCHECK_NE(surface_id_, SurfaceManager::kNoSurfaceID); 1326 DCHECK_NE(config_.surface_id, SurfaceManager::kNoSurfaceID);
1329 1327
1330 // The leaving fullscreen notification may come in before this point. 1328 // The leaving fullscreen notification may come in before this point.
1331 if (pending_surface_id_) 1329 if (pending_surface_id_)
1332 DCHECK_EQ(pending_surface_id_.value(), SurfaceManager::kNoSurfaceID); 1330 DCHECK_EQ(pending_surface_id_.value(), SurfaceManager::kNoSurfaceID);
1333 1331
1334 pending_surface_id_ = SurfaceManager::kNoSurfaceID; 1332 pending_surface_id_ = SurfaceManager::kNoSurfaceID;
1335 UpdateSurface(); 1333 UpdateSurface();
1336 return; 1334 return;
1337 } 1335 }
1338 1336
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1587 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() 1585 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden()
1588 const { 1586 const {
1589 // Prevent MediaCodec from using its internal software decoders when we have 1587 // Prevent MediaCodec from using its internal software decoders when we have
1590 // more secure and up to date versions in the renderer process. 1588 // more secure and up to date versions in the renderer process.
1591 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 || 1589 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 ||
1592 codec_config_->codec_ == kCodecVP9); 1590 codec_config_->codec_ == kCodecVP9);
1593 } 1591 }
1594 1592
1595 bool AndroidVideoDecodeAccelerator::UpdateSurface() { 1593 bool AndroidVideoDecodeAccelerator::UpdateSurface() {
1596 DCHECK(pending_surface_id_); 1594 DCHECK(pending_surface_id_);
1597 DCHECK_NE(surface_id_, pending_surface_id_.value()); 1595 DCHECK_NE(config_.surface_id, pending_surface_id_.value());
1598 1596
1599 // Ensure the current context is active when switching surfaces; we may need 1597 // Ensure the current context is active when switching surfaces; we may need
1600 // to create a new texture. 1598 // to create a new texture.
1601 if (!make_context_current_cb_.Run()) { 1599 if (!make_context_current_cb_.Run()) {
1602 NOTIFY_ERROR(PLATFORM_FAILURE, 1600 NOTIFY_ERROR(PLATFORM_FAILURE,
1603 "Failed to make this decoder's GL context current when " 1601 "Failed to make this decoder's GL context current when "
1604 "switching surfaces."); 1602 "switching surfaces.");
1605 return false; 1603 return false;
1606 } 1604 }
1607 1605
1608 surface_id_ = pending_surface_id_.value(); 1606 config_.surface_id = pending_surface_id_.value();
1609 codec_config_->surface_ = 1607 codec_config_->surface_ =
1610 picture_buffer_manager_.Initialize(pending_surface_id_.value()); 1608 picture_buffer_manager_.Initialize(pending_surface_id_.value());
1611 if (codec_config_->surface_.IsEmpty()) { 1609 if (codec_config_->surface_.IsEmpty()) {
1612 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces."); 1610 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces.");
1613 return false; 1611 return false;
1614 } 1612 }
1615 1613
1616 if (media_codec_ && 1614 if (media_codec_ &&
1617 !media_codec_->SetSurface(codec_config_->surface_.j_surface().obj())) { 1615 !media_codec_->SetSurface(codec_config_->surface_.j_surface().obj())) {
1618 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces."); 1616 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces.");
1619 return false; 1617 return false;
1620 } 1618 }
1621 1619
1622 pending_surface_id_.reset(); 1620 pending_surface_id_.reset();
1623 return true; 1621 return true;
1624 } 1622 }
1625 1623
1626 } // namespace media 1624 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/android_video_decode_accelerator.h ('k') | media/gpu/ipc/common/media_param_traits_macros.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698