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

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

Issue 1920093003: media: Handle output SurfaceView destruction in AVDA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@svteardown
Patch Set: Dale's comments and disable VP8 on platforms where we do surface teardown Created 4 years, 7 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/gpu/android_video_decode_accelerator.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) 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 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 is_encrypted_(false), 311 is_encrypted_(false),
312 state_(NO_ERROR), 312 state_(NO_ERROR),
313 picturebuffers_requested_(false), 313 picturebuffers_requested_(false),
314 drain_type_(DRAIN_TYPE_NONE), 314 drain_type_(DRAIN_TYPE_NONE),
315 media_drm_bridge_cdm_context_(nullptr), 315 media_drm_bridge_cdm_context_(nullptr),
316 cdm_registration_id_(0), 316 cdm_registration_id_(0),
317 pending_input_buf_index_(-1), 317 pending_input_buf_index_(-1),
318 error_sequence_token_(0), 318 error_sequence_token_(0),
319 defer_errors_(false), 319 defer_errors_(false),
320 deferred_initialization_pending_(false), 320 deferred_initialization_pending_(false),
321 surface_id_(media::VideoDecodeAccelerator::Config::kNoSurfaceID),
321 weak_this_factory_(this) {} 322 weak_this_factory_(this) {}
322 323
323 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 324 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
324 DCHECK(thread_checker_.CalledOnValidThread()); 325 DCHECK(thread_checker_.CalledOnValidThread());
325 g_avda_timer.Pointer()->StopTimer(this); 326 g_avda_timer.Pointer()->StopTimer(this);
326 g_avda_timer.Pointer()->StopThread(this); 327 g_avda_timer.Pointer()->StopThread(this);
327 328
328 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 329 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
329 if (!media_drm_bridge_cdm_context_) 330 if (!media_drm_bridge_cdm_context_)
330 return; 331 return;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 } else { 409 } else {
409 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; 410 DVLOG(1) << __FUNCTION__ << ", using copy back strategy.";
410 strategy_.reset(new AndroidCopyingBackingStrategy(this)); 411 strategy_.reset(new AndroidCopyingBackingStrategy(this));
411 } 412 }
412 413
413 if (!make_context_current_cb_.Run()) { 414 if (!make_context_current_cb_.Run()) {
414 LOG(ERROR) << "Failed to make this decoder's GL context current."; 415 LOG(ERROR) << "Failed to make this decoder's GL context current.";
415 return false; 416 return false;
416 } 417 }
417 418
418 codec_config_->surface_ = strategy_->Initialize(config.surface_id); 419 surface_id_ = config.surface_id;
420 codec_config_->surface_ = strategy_->Initialize(surface_id_);
419 if (codec_config_->surface_.IsEmpty()) { 421 if (codec_config_->surface_.IsEmpty()) {
420 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " 422 LOG(ERROR) << "Failed to initialize the backing strategy. The returned "
421 "Java surface is empty."; 423 "Java surface is empty.";
422 return false; 424 return false;
423 } 425 }
424 426
427 on_destroying_surface_cb_ =
428 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface,
429 weak_this_factory_.GetWeakPtr());
430 AVDASurfaceTracker::GetInstance()->RegisterOnDestroyingSurfaceCallback(
431 on_destroying_surface_cb_);
432
425 // TODO(watk,liberato): move this into the strategy. 433 // TODO(watk,liberato): move this into the strategy.
426 scoped_refptr<gfx::SurfaceTexture> surface_texture = 434 scoped_refptr<gfx::SurfaceTexture> surface_texture =
427 strategy_->GetSurfaceTexture(); 435 strategy_->GetSurfaceTexture();
428 if (surface_texture) { 436 if (surface_texture) {
429 on_frame_available_handler_ = 437 on_frame_available_handler_ =
430 new OnFrameAvailableHandler(this, surface_texture); 438 new OnFrameAvailableHandler(this, surface_texture);
431 } 439 }
432 440
433 // Start the thread for async configuration, even if we don't need it now. 441 // Start the thread for async configuration, even if we don't need it now.
434 // ResetCodecState might rebuild the codec later, for example. 442 // ResetCodecState might rebuild the codec later, for example.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 504
497 NOTIMPLEMENTED(); 505 NOTIMPLEMENTED();
498 NotifyInitializationComplete(false); 506 NotifyInitializationComplete(false);
499 507
500 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 508 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
501 } 509 }
502 510
503 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { 511 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) {
504 DCHECK(thread_checker_.CalledOnValidThread()); 512 DCHECK(thread_checker_.CalledOnValidThread());
505 TRACE_EVENT0("media", "AVDA::DoIOTask"); 513 TRACE_EVENT0("media", "AVDA::DoIOTask");
506 if (state_ == ERROR || state_ == WAITING_FOR_CODEC) 514 if (state_ == ERROR || state_ == WAITING_FOR_CODEC ||
515 state_ == SURFACE_DESTROYED) {
507 return; 516 return;
517 }
508 518
509 strategy_->MaybeRenderEarly(); 519 strategy_->MaybeRenderEarly();
510 bool did_work = false, did_input = false, did_output = false; 520 bool did_work = false, did_input = false, did_output = false;
511 do { 521 do {
512 did_input = QueueInput(); 522 did_input = QueueInput();
513 did_output = DequeueOutput(); 523 did_output = DequeueOutput();
514 if (did_input || did_output) 524 if (did_input || did_output)
515 did_work = true; 525 did_work = true;
516 } while (did_input || did_output); 526 } while (did_input || did_output);
517 527
(...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 } 947 }
938 948
939 strategy_->ReuseOnePictureBuffer(i->second); 949 strategy_->ReuseOnePictureBuffer(i->second);
940 DoIOTask(true); 950 DoIOTask(true);
941 } 951 }
942 952
943 void AndroidVideoDecodeAccelerator::Flush() { 953 void AndroidVideoDecodeAccelerator::Flush() {
944 DVLOG(1) << __FUNCTION__; 954 DVLOG(1) << __FUNCTION__;
945 DCHECK(thread_checker_.CalledOnValidThread()); 955 DCHECK(thread_checker_.CalledOnValidThread());
946 956
947 StartCodecDrain(DRAIN_FOR_FLUSH); 957 if (state_ == SURFACE_DESTROYED)
958 NotifyFlushDone();
959 else
960 StartCodecDrain(DRAIN_FOR_FLUSH);
948 } 961 }
949 962
950 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { 963 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() {
951 DCHECK(thread_checker_.CalledOnValidThread()); 964 DCHECK(thread_checker_.CalledOnValidThread());
952 965
953 // It's probably okay just to return here, since the codec will be configured 966 // It's probably okay just to return here, since the codec will be configured
954 // asynchronously. It's unclear that any state for the new request could 967 // asynchronously. It's unclear that any state for the new request could
955 // be different, unless somebody modifies |codec_config_| while we're already 968 // be different, unless somebody modifies |codec_config_| while we're already
956 // waiting for a codec. One shouldn't do that for thread safety. 969 // waiting for a codec. One shouldn't do that for thread safety.
957 DCHECK_NE(state_, WAITING_FOR_CODEC); 970 DCHECK_NE(state_, WAITING_FOR_CODEC);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 return std::unique_ptr<media::VideoCodecBridge>( 1016 return std::unique_ptr<media::VideoCodecBridge>(
1004 media::VideoCodecBridge::CreateDecoder( 1017 media::VideoCodecBridge::CreateDecoder(
1005 codec_config->codec_, codec_config->needs_protected_surface_, 1018 codec_config->codec_, codec_config->needs_protected_surface_,
1006 codec_config->initial_expected_coded_size_, 1019 codec_config->initial_expected_coded_size_,
1007 codec_config->surface_.j_surface().obj(), media_crypto, true)); 1020 codec_config->surface_.j_surface().obj(), media_crypto, true));
1008 } 1021 }
1009 1022
1010 void AndroidVideoDecodeAccelerator::OnCodecConfigured( 1023 void AndroidVideoDecodeAccelerator::OnCodecConfigured(
1011 std::unique_ptr<media::VideoCodecBridge> media_codec) { 1024 std::unique_ptr<media::VideoCodecBridge> media_codec) {
1012 DCHECK(thread_checker_.CalledOnValidThread()); 1025 DCHECK(thread_checker_.CalledOnValidThread());
1013 DCHECK_EQ(state_, WAITING_FOR_CODEC); 1026 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED);
1014
1015 media_codec_ = std::move(media_codec);
1016 1027
1017 // Record one instance of the codec being initialized. 1028 // Record one instance of the codec being initialized.
1018 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); 1029 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized);
1019 1030
1020 strategy_->CodecChanged(media_codec_.get());
1021
1022 // If we are supposed to notify that initialization is complete, then do so 1031 // If we are supposed to notify that initialization is complete, then do so
1023 // now. Otherwise, this is a reconfiguration. 1032 // now. Otherwise, this is a reconfiguration.
1024 if (deferred_initialization_pending_) { 1033 if (deferred_initialization_pending_) {
1025 NotifyInitializationComplete(!!media_codec_); 1034 // Losing the output surface is not considered an error state, so notify
1035 // success. The client will destroy this soon.
1036 NotifyInitializationComplete(state_ == SURFACE_DESTROYED ? true
1037 : !!media_codec);
1026 deferred_initialization_pending_ = false; 1038 deferred_initialization_pending_ = false;
1027 } 1039 }
1028 1040
1041 // If |state_| changed to SURFACE_DESTROYED while we were configuring a codec,
1042 // then the codec is already invalid so we return early and drop it.
1043 if (state_ == SURFACE_DESTROYED)
1044 return;
1045
1046 media_codec_ = std::move(media_codec);
1047 strategy_->CodecChanged(media_codec_.get());
1029 if (!media_codec_) { 1048 if (!media_codec_) {
1030 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec."); 1049 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec.");
1031 return; 1050 return;
1032 } 1051 }
1033 1052
1034 state_ = NO_ERROR; 1053 state_ = NO_ERROR;
1035 1054
1036 ManageTimer(true); 1055 ManageTimer(true);
1037 } 1056 }
1038 1057
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 } 1113 }
1095 drain_type_ = DRAIN_TYPE_NONE; 1114 drain_type_ = DRAIN_TYPE_NONE;
1096 } 1115 }
1097 1116
1098 void AndroidVideoDecodeAccelerator::ResetCodecState( 1117 void AndroidVideoDecodeAccelerator::ResetCodecState(
1099 const base::Closure& done_cb) { 1118 const base::Closure& done_cb) {
1100 DCHECK(thread_checker_.CalledOnValidThread()); 1119 DCHECK(thread_checker_.CalledOnValidThread());
1101 1120
1102 // If there is already a reset in flight, then that counts. This can really 1121 // If there is already a reset in flight, then that counts. This can really
1103 // only happen if somebody calls Reset. 1122 // only happen if somebody calls Reset.
1104 if (state_ == WAITING_FOR_CODEC) { 1123 // If the surface is destroyed there's nothing to do.
1124 if (state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED) {
1105 if (!done_cb.is_null()) 1125 if (!done_cb.is_null())
1106 done_cb.Run(); 1126 done_cb.Run();
1107 return; 1127 return;
1108 } 1128 }
1109 1129
1110 bitstream_buffers_in_decoder_.clear(); 1130 bitstream_buffers_in_decoder_.clear();
1111 1131
1112 if (pending_input_buf_index_ != -1) { 1132 if (pending_input_buf_index_ != -1) {
1113 // The data for that index exists in the input buffer, but corresponding 1133 // The data for that index exists in the input buffer, but corresponding
1114 // shm block been deleted. Check that it is safe to flush the coec, i.e. 1134 // shm block been deleted. Check that it is safe to flush the coec, i.e.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 StartCodecDrain(DRAIN_FOR_DESTROY); 1241 StartCodecDrain(DRAIN_FOR_DESTROY);
1222 } else { 1242 } else {
1223 ActualDestroy(); 1243 ActualDestroy();
1224 } 1244 }
1225 } 1245 }
1226 1246
1227 void AndroidVideoDecodeAccelerator::ActualDestroy() { 1247 void AndroidVideoDecodeAccelerator::ActualDestroy() {
1228 DVLOG(1) << __FUNCTION__; 1248 DVLOG(1) << __FUNCTION__;
1229 DCHECK(thread_checker_.CalledOnValidThread()); 1249 DCHECK(thread_checker_.CalledOnValidThread());
1230 1250
1251 if (!on_destroying_surface_cb_.is_null()) {
1252 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback(
1253 on_destroying_surface_cb_);
1254 }
1255
1231 // Note that async codec construction might still be in progress. In that 1256 // Note that async codec construction might still be in progress. In that
1232 // case, the codec will be deleted when it completes once we invalidate all 1257 // case, the codec will be deleted when it completes once we invalidate all
1233 // our weak refs. 1258 // our weak refs.
1234 weak_this_factory_.InvalidateWeakPtrs(); 1259 weak_this_factory_.InvalidateWeakPtrs();
1235 if (media_codec_) { 1260 if (media_codec_) {
1236 g_avda_timer.Pointer()->StopTimer(this); 1261 g_avda_timer.Pointer()->StopTimer(this);
1237 media_codec_.reset(); 1262 media_codec_.reset();
1238 } 1263 }
1239 delete this; 1264 delete this;
1240 } 1265 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 1299
1275 DCHECK_LE(1u, picture_buffer.internal_texture_ids().size()); 1300 DCHECK_LE(1u, picture_buffer.internal_texture_ids().size());
1276 gpu::gles2::TextureRef* texture_ref = 1301 gpu::gles2::TextureRef* texture_ref =
1277 texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]); 1302 texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]);
1278 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE, 1303 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE,
1279 nullptr); 1304 nullptr);
1280 1305
1281 return texture_ref; 1306 return texture_ref;
1282 } 1307 }
1283 1308
1309 void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) {
1310 DCHECK(thread_checker_.CalledOnValidThread());
1311 TRACE_EVENT0("media", "AVDA::OnDestroyingSurface");
1312 DVLOG(1) << __FUNCTION__ << " surface_id: " << surface_id;
1313
1314 if (surface_id != surface_id_)
1315 return;
1316
1317 // If we're currently asynchronously configuring a codec, it will be destroyed
1318 // when configuration completes and it notices that |state_| has changed to
1319 // SURFACE_DESTROYED.
1320 state_ = SURFACE_DESTROYED;
1321 if (media_codec_) {
1322 media_codec_.reset();
1323 strategy_->CodecChanged(media_codec_.get());
1324 }
1325 // If we're draining, signal completion now because the drain can no longer
1326 // proceed.
1327 if (drain_type_ != DRAIN_TYPE_NONE)
1328 OnDrainCompleted();
1329 }
1330
1284 void AndroidVideoDecodeAccelerator::OnFrameAvailable() { 1331 void AndroidVideoDecodeAccelerator::OnFrameAvailable() {
1285 // Remember: this may be on any thread. 1332 // Remember: this may be on any thread.
1286 DCHECK(strategy_); 1333 DCHECK(strategy_);
1287 strategy_->OnFrameAvailable(); 1334 strategy_->OnFrameAvailable();
1288 } 1335 }
1289 1336
1290 void AndroidVideoDecodeAccelerator::PostError( 1337 void AndroidVideoDecodeAccelerator::PostError(
1291 const ::tracked_objects::Location& from_here, 1338 const ::tracked_objects::Location& from_here,
1292 media::VideoDecodeAccelerator::Error error) { 1339 media::VideoDecodeAccelerator::Error error) {
1293 base::MessageLoop::current()->PostDelayedTask( 1340 base::MessageLoop::current()->PostDelayedTask(
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1400 return !gpu_preferences.enable_threaded_texture_mailboxes; 1447 return !gpu_preferences.enable_threaded_texture_mailboxes;
1401 } 1448 }
1402 1449
1403 // static 1450 // static
1404 media::VideoDecodeAccelerator::Capabilities 1451 media::VideoDecodeAccelerator::Capabilities
1405 AndroidVideoDecodeAccelerator::GetCapabilities( 1452 AndroidVideoDecodeAccelerator::GetCapabilities(
1406 const gpu::GpuPreferences& gpu_preferences) { 1453 const gpu::GpuPreferences& gpu_preferences) {
1407 Capabilities capabilities; 1454 Capabilities capabilities;
1408 SupportedProfiles& profiles = capabilities.supported_profiles; 1455 SupportedProfiles& profiles = capabilities.supported_profiles;
1409 1456
1410 if (media::MediaCodecUtil::IsVp8DecoderAvailable()) { 1457 // Only support VP8 on Android versions where we don't have to synchronously
1458 // tear down the MediaCodec on surface destruction because VP8 requires
1459 // us to completely drain the decoder before releasing it, which is difficult
1460 // and time consuming to do while the surface is being destroyed.
1461 if (base::android::BuildInfo::GetInstance()->sdk_int() >= 18 &&
liberato (no reviews please) 2016/05/11 22:09:00 should this be > rather than >= ? 18 is JB i thin
1462 media::MediaCodecUtil::IsVp8DecoderAvailable()) {
1411 SupportedProfile profile; 1463 SupportedProfile profile;
1412 profile.profile = media::VP8PROFILE_ANY; 1464 profile.profile = media::VP8PROFILE_ANY;
1413 profile.min_resolution.SetSize(0, 0); 1465 profile.min_resolution.SetSize(0, 0);
1414 profile.max_resolution.SetSize(1920, 1088); 1466 profile.max_resolution.SetSize(1920, 1088);
1415 // If we know MediaCodec will just create a software codec, prefer our 1467 // If we know MediaCodec will just create a software codec, prefer our
1416 // internal software decoder instead. It's more up to date and secured 1468 // internal software decoder instead. It's more up to date and secured
1417 // within the renderer sandbox. However if the content is encrypted, we 1469 // within the renderer sandbox. However if the content is encrypted, we
1418 // must use MediaCodec anyways since MediaDrm offers no way to decrypt 1470 // must use MediaCodec anyways since MediaDrm offers no way to decrypt
1419 // the buffers and let us use our internal software decoders. 1471 // the buffers and let us use our internal software decoders.
1420 profile.encrypted_only = media::VideoCodecBridge::IsKnownUnaccelerated( 1472 profile.encrypted_only = media::VideoCodecBridge::IsKnownUnaccelerated(
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { 1514 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) {
1463 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: 1515 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities::
1464 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; 1516 SUPPORTS_EXTERNAL_OUTPUT_SURFACE;
1465 } 1517 }
1466 } 1518 }
1467 1519
1468 return capabilities; 1520 return capabilities;
1469 } 1521 }
1470 1522
1471 } // namespace media 1523 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/android_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698