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

Side by Side Diff: content/common/gpu/media/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: Comments + drain and flush logic 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 | « content/common/gpu/media/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 "content/common/gpu/media/android_video_decode_accelerator.h" 5 #include "content/common/gpu/media/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 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 is_encrypted_(false), 312 is_encrypted_(false),
313 state_(NO_ERROR), 313 state_(NO_ERROR),
314 picturebuffers_requested_(false), 314 picturebuffers_requested_(false),
315 drain_type_(DRAIN_TYPE_NONE), 315 drain_type_(DRAIN_TYPE_NONE),
316 media_drm_bridge_cdm_context_(nullptr), 316 media_drm_bridge_cdm_context_(nullptr),
317 cdm_registration_id_(0), 317 cdm_registration_id_(0),
318 pending_input_buf_index_(-1), 318 pending_input_buf_index_(-1),
319 error_sequence_token_(0), 319 error_sequence_token_(0),
320 defer_errors_(false), 320 defer_errors_(false),
321 deferred_initialization_pending_(false), 321 deferred_initialization_pending_(false),
322 surface_id_(media::VideoDecodeAccelerator::Config::kNoSurfaceID),
322 weak_this_factory_(this) {} 323 weak_this_factory_(this) {}
323 324
324 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 325 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
325 DCHECK(thread_checker_.CalledOnValidThread()); 326 DCHECK(thread_checker_.CalledOnValidThread());
326 g_avda_timer.Pointer()->StopTimer(this); 327 g_avda_timer.Pointer()->StopTimer(this);
327 g_avda_timer.Pointer()->StopThread(this); 328 g_avda_timer.Pointer()->StopThread(this);
328 329
329 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 330 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
330 if (!media_drm_bridge_cdm_context_) 331 if (!media_drm_bridge_cdm_context_)
331 return; 332 return;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 } else { 410 } else {
410 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; 411 DVLOG(1) << __FUNCTION__ << ", using copy back strategy.";
411 strategy_.reset(new AndroidCopyingBackingStrategy(this)); 412 strategy_.reset(new AndroidCopyingBackingStrategy(this));
412 } 413 }
413 414
414 if (!make_context_current_cb_.Run()) { 415 if (!make_context_current_cb_.Run()) {
415 LOG(ERROR) << "Failed to make this decoder's GL context current."; 416 LOG(ERROR) << "Failed to make this decoder's GL context current.";
416 return false; 417 return false;
417 } 418 }
418 419
419 codec_config_->surface_ = strategy_->Initialize(config.surface_id); 420 surface_id_ = config.surface_id;
421 codec_config_->surface_ = strategy_->Initialize(surface_id_);
420 if (codec_config_->surface_.IsEmpty()) { 422 if (codec_config_->surface_.IsEmpty()) {
421 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " 423 LOG(ERROR) << "Failed to initialize the backing strategy. The returned "
422 "Java surface is empty."; 424 "Java surface is empty.";
423 return false; 425 return false;
424 } 426 }
425 427
428 on_destroying_surface_cb_ =
429 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface,
430 weak_this_factory_.GetWeakPtr());
431 AVDASurfaceTracker::GetInstance()->RegisterOnDestroyingSurfaceCallback(
432 on_destroying_surface_cb_);
433
426 // TODO(watk,liberato): move this into the strategy. 434 // TODO(watk,liberato): move this into the strategy.
427 scoped_refptr<gfx::SurfaceTexture> surface_texture = 435 scoped_refptr<gfx::SurfaceTexture> surface_texture =
428 strategy_->GetSurfaceTexture(); 436 strategy_->GetSurfaceTexture();
429 if (surface_texture) { 437 if (surface_texture) {
430 on_frame_available_handler_ = 438 on_frame_available_handler_ =
431 new OnFrameAvailableHandler(this, surface_texture); 439 new OnFrameAvailableHandler(this, surface_texture);
432 } 440 }
433 441
434 // Start the thread for async configuration, even if we don't need it now. 442 // Start the thread for async configuration, even if we don't need it now.
435 // ResetCodecState might rebuild the codec later, for example. 443 // ResetCodecState might rebuild the codec later, for example.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 505
498 NOTIMPLEMENTED(); 506 NOTIMPLEMENTED();
499 NotifyInitializationComplete(false); 507 NotifyInitializationComplete(false);
500 508
501 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 509 #endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
502 } 510 }
503 511
504 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { 512 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) {
505 DCHECK(thread_checker_.CalledOnValidThread()); 513 DCHECK(thread_checker_.CalledOnValidThread());
506 TRACE_EVENT0("media", "AVDA::DoIOTask"); 514 TRACE_EVENT0("media", "AVDA::DoIOTask");
507 if (state_ == ERROR || state_ == WAITING_FOR_CODEC) 515 if (state_ == ERROR || state_ == WAITING_FOR_CODEC ||
516 state_ == SURFACE_DESTROYED) {
508 return; 517 return;
518 }
509 519
510 strategy_->MaybeRenderEarly(); 520 strategy_->MaybeRenderEarly();
511 bool did_work = QueueInput(); 521 bool did_work = QueueInput();
512 while (DequeueOutput()) 522 while (DequeueOutput())
513 did_work = true; 523 did_work = true;
514 524
515 ManageTimer(did_work || start_timer); 525 ManageTimer(did_work || start_timer);
516 } 526 }
517 527
518 bool AndroidVideoDecodeAccelerator::QueueInput() { 528 bool AndroidVideoDecodeAccelerator::QueueInput() {
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 } 943 }
934 944
935 strategy_->ReuseOnePictureBuffer(i->second); 945 strategy_->ReuseOnePictureBuffer(i->second);
936 DoIOTask(true); 946 DoIOTask(true);
937 } 947 }
938 948
939 void AndroidVideoDecodeAccelerator::Flush() { 949 void AndroidVideoDecodeAccelerator::Flush() {
940 DVLOG(1) << __FUNCTION__; 950 DVLOG(1) << __FUNCTION__;
941 DCHECK(thread_checker_.CalledOnValidThread()); 951 DCHECK(thread_checker_.CalledOnValidThread());
942 952
943 StartCodecDrain(DRAIN_FOR_FLUSH); 953 if (state_ == SURFACE_DESTROYED) {
DaleCurtis 2016/04/27 21:20:35 No unnecessary parens.
954 NotifyFlushDone();
955 } else {
956 StartCodecDrain(DRAIN_FOR_FLUSH);
957 }
944 } 958 }
945 959
946 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { 960 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() {
947 DCHECK(thread_checker_.CalledOnValidThread()); 961 DCHECK(thread_checker_.CalledOnValidThread());
948 962
949 // It's probably okay just to return here, since the codec will be configured 963 // It's probably okay just to return here, since the codec will be configured
950 // asynchronously. It's unclear that any state for the new request could 964 // asynchronously. It's unclear that any state for the new request could
951 // be different, unless somebody modifies |codec_config_| while we're already 965 // be different, unless somebody modifies |codec_config_| while we're already
952 // waiting for a codec. One shouldn't do that for thread safety. 966 // waiting for a codec. One shouldn't do that for thread safety.
953 DCHECK_NE(state_, WAITING_FOR_CODEC); 967 DCHECK_NE(state_, WAITING_FOR_CODEC);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
999 return std::unique_ptr<media::VideoCodecBridge>( 1013 return std::unique_ptr<media::VideoCodecBridge>(
1000 media::VideoCodecBridge::CreateDecoder( 1014 media::VideoCodecBridge::CreateDecoder(
1001 codec_config->codec_, codec_config->needs_protected_surface_, 1015 codec_config->codec_, codec_config->needs_protected_surface_,
1002 codec_config->initial_expected_coded_size_, 1016 codec_config->initial_expected_coded_size_,
1003 codec_config->surface_.j_surface().obj(), media_crypto, true)); 1017 codec_config->surface_.j_surface().obj(), media_crypto, true));
1004 } 1018 }
1005 1019
1006 void AndroidVideoDecodeAccelerator::OnCodecConfigured( 1020 void AndroidVideoDecodeAccelerator::OnCodecConfigured(
1007 std::unique_ptr<media::VideoCodecBridge> media_codec) { 1021 std::unique_ptr<media::VideoCodecBridge> media_codec) {
1008 DCHECK(thread_checker_.CalledOnValidThread()); 1022 DCHECK(thread_checker_.CalledOnValidThread());
1009 DCHECK_EQ(state_, WAITING_FOR_CODEC); 1023 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED);
1010
1011 media_codec_ = std::move(media_codec);
1012 1024
1013 // Record one instance of the codec being initialized. 1025 // Record one instance of the codec being initialized.
1014 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); 1026 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized);
1015 1027
1016 strategy_->CodecChanged(media_codec_.get());
1017
1018 // If we are supposed to notify that initialization is complete, then do so 1028 // If we are supposed to notify that initialization is complete, then do so
1019 // now. Otherwise, this is a reconfiguration. 1029 // now. Otherwise, this is a reconfiguration.
1020 if (deferred_initialization_pending_) { 1030 if (deferred_initialization_pending_) {
1021 NotifyInitializationComplete(!!media_codec_); 1031 // Losing the output surface is not considered an error state, so notify
1032 // success. The client will destroy this soon.
1033 NotifyInitializationComplete(state_ == SURFACE_DESTROYED ? true
1034 : !!media_codec);
1022 deferred_initialization_pending_ = false; 1035 deferred_initialization_pending_ = false;
1023 } 1036 }
1024 1037
1038 // If |state_| changed to SURFACE_DESTROYED while we were configuring a codec,
1039 // then the codec is already invalid so we return early and drop it.
1040 if (state_ == SURFACE_DESTROYED)
1041 return;
1042
1043 media_codec_ = std::move(media_codec);
1044 strategy_->CodecChanged(media_codec_.get());
1025 if (!media_codec_) { 1045 if (!media_codec_) {
1026 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec."); 1046 POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec.");
1027 return; 1047 return;
1028 } 1048 }
1029 1049
1030 state_ = NO_ERROR; 1050 state_ = NO_ERROR;
1031 1051
1032 ManageTimer(true); 1052 ManageTimer(true);
1033 } 1053 }
1034 1054
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 } 1110 }
1091 drain_type_ = DRAIN_TYPE_NONE; 1111 drain_type_ = DRAIN_TYPE_NONE;
1092 } 1112 }
1093 1113
1094 void AndroidVideoDecodeAccelerator::ResetCodecState( 1114 void AndroidVideoDecodeAccelerator::ResetCodecState(
1095 const base::Closure& done_cb) { 1115 const base::Closure& done_cb) {
1096 DCHECK(thread_checker_.CalledOnValidThread()); 1116 DCHECK(thread_checker_.CalledOnValidThread());
1097 1117
1098 // If there is already a reset in flight, then that counts. This can really 1118 // If there is already a reset in flight, then that counts. This can really
1099 // only happen if somebody calls Reset. 1119 // only happen if somebody calls Reset.
1100 if (state_ == WAITING_FOR_CODEC) { 1120 // If the surface is destroyed there's nothing to do.
1121 if (state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED) {
1101 if (!done_cb.is_null()) 1122 if (!done_cb.is_null())
1102 done_cb.Run(); 1123 done_cb.Run();
1103 return; 1124 return;
1104 } 1125 }
1105 1126
1106 bitstream_buffers_in_decoder_.clear(); 1127 bitstream_buffers_in_decoder_.clear();
1107 1128
1108 if (pending_input_buf_index_ != -1) { 1129 if (pending_input_buf_index_ != -1) {
1109 // The data for that index exists in the input buffer, but corresponding 1130 // The data for that index exists in the input buffer, but corresponding
1110 // shm block been deleted. Check that it is safe to flush the coec, i.e. 1131 // 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
1217 StartCodecDrain(DRAIN_FOR_DESTROY); 1238 StartCodecDrain(DRAIN_FOR_DESTROY);
1218 } else { 1239 } else {
1219 ActualDestroy(); 1240 ActualDestroy();
1220 } 1241 }
1221 } 1242 }
1222 1243
1223 void AndroidVideoDecodeAccelerator::ActualDestroy() { 1244 void AndroidVideoDecodeAccelerator::ActualDestroy() {
1224 DVLOG(1) << __FUNCTION__; 1245 DVLOG(1) << __FUNCTION__;
1225 DCHECK(thread_checker_.CalledOnValidThread()); 1246 DCHECK(thread_checker_.CalledOnValidThread());
1226 1247
1248 if (!on_destroying_surface_cb_.is_null()) {
1249 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback(
1250 on_destroying_surface_cb_);
1251 }
DaleCurtis 2016/04/27 21:20:35 Clear surface destruction cb?
1252
1227 // Note that async codec construction might still be in progress. In that 1253 // Note that async codec construction might still be in progress. In that
1228 // case, the codec will be deleted when it completes once we invalidate all 1254 // case, the codec will be deleted when it completes once we invalidate all
1229 // our weak refs. 1255 // our weak refs.
1230 weak_this_factory_.InvalidateWeakPtrs(); 1256 weak_this_factory_.InvalidateWeakPtrs();
1231 if (media_codec_) { 1257 if (media_codec_) {
1232 g_avda_timer.Pointer()->StopTimer(this); 1258 g_avda_timer.Pointer()->StopTimer(this);
1233 media_codec_.reset(); 1259 media_codec_.reset();
1234 } 1260 }
1235 delete this; 1261 delete this;
1236 } 1262 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1270 1296
1271 DCHECK_LE(1u, picture_buffer.internal_texture_ids().size()); 1297 DCHECK_LE(1u, picture_buffer.internal_texture_ids().size());
1272 gpu::gles2::TextureRef* texture_ref = 1298 gpu::gles2::TextureRef* texture_ref =
1273 texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]); 1299 texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]);
1274 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE, 1300 RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE,
1275 nullptr); 1301 nullptr);
1276 1302
1277 return texture_ref; 1303 return texture_ref;
1278 } 1304 }
1279 1305
1306 void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) {
1307 DCHECK(thread_checker_.CalledOnValidThread());
1308 TRACE_EVENT0("media", "AVDA::OnDestroyingSurface");
1309 DVLOG(1) << __FUNCTION__ << " surface_id: " << surface_id;
1310
1311 if (surface_id != surface_id_)
1312 return;
1313
1314 // If we're currently asynchronously configuring a codec, it will be destroyed
DaleCurtis 2016/04/27 21:20:35 Hmm, this may have bad interactions where we need
watk 2016/05/02 17:49:00 Oh, good point. :( This is going to be painful.
1315 // when configuration completes and it notices that |state_| has changed to
1316 // SURFACE_DESTROYED.
1317 state_ = SURFACE_DESTROYED;
1318 if (media_codec_) {
1319 media_codec_.reset();
1320 strategy_->CodecChanged(media_codec_.get());
1321 }
1322 // If we're draining, signal completion now because the drain can no longer
DaleCurtis 2016/04/27 21:20:35 Line above.
1323 // proceed.
1324 if (drain_type_ != DRAIN_TYPE_NONE) {
DaleCurtis 2016/04/27 21:20:36 No unnecessary parens.
1325 OnDrainCompleted();
1326 }
1327 }
1328
1280 void AndroidVideoDecodeAccelerator::OnFrameAvailable() { 1329 void AndroidVideoDecodeAccelerator::OnFrameAvailable() {
1281 // Remember: this may be on any thread. 1330 // Remember: this may be on any thread.
1282 DCHECK(strategy_); 1331 DCHECK(strategy_);
1283 strategy_->OnFrameAvailable(); 1332 strategy_->OnFrameAvailable();
1284 } 1333 }
1285 1334
1286 void AndroidVideoDecodeAccelerator::PostError( 1335 void AndroidVideoDecodeAccelerator::PostError(
1287 const ::tracked_objects::Location& from_here, 1336 const ::tracked_objects::Location& from_here,
1288 media::VideoDecodeAccelerator::Error error) { 1337 media::VideoDecodeAccelerator::Error error) {
1289 base::MessageLoop::current()->PostDelayedTask( 1338 base::MessageLoop::current()->PostDelayedTask(
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { 1507 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) {
1459 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: 1508 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities::
1460 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; 1509 SUPPORTS_EXTERNAL_OUTPUT_SURFACE;
1461 } 1510 }
1462 } 1511 }
1463 1512
1464 return capabilities; 1513 return capabilities;
1465 } 1514 }
1466 1515
1467 } // namespace content 1516 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/android_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698