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

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

Issue 1993833002: Serialize usage of SurfaceView between AVDA instances. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments. 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
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 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 io_timer_.Stop(); 242 io_timer_.Stop();
243 } 243 }
244 244
245 // Eventually, we should run the timer on this thread. For now, we just keep 245 // Eventually, we should run the timer on this thread. For now, we just keep
246 // it as a convenience for construction. 246 // it as a convenience for construction.
247 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { 247 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() {
248 DCHECK(thread_checker_.CalledOnValidThread()); 248 DCHECK(thread_checker_.CalledOnValidThread());
249 return construction_thread_.task_runner(); 249 return construction_thread_.task_runner();
250 } 250 }
251 251
252 // |owner| would like to use |surface_id|. If it is not busy, then mark it
watk 2016/05/18 20:38:18 No "owner" any more
liberato (no reviews please) 2016/05/18 21:13:13 Done.
253 // as busy and return true. If it is busy, then replace any existing waiter,
254 // make |owner| the current waiter, and return false. Any existing waiter
255 // is assumed to be on the way out, so we fail its allocation request.
256 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
257 SurfaceWaiterMap::iterator iter = surface_waiter_map_.find(surface_id);
258
259 // Nobody has to wait for no surface.
DaleCurtis 2016/05/18 17:59:11 Move above find?
liberato (no reviews please) 2016/05/18 18:49:39 Done.
260 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID)
261 return true;
262
263 if (iter == surface_waiter_map_.end()) {
264 // SurfaceView isn't allocated. Succeed.
265 surface_waiter_map_[surface_id].owner = avda;
266 surface_waiter_map_[surface_id].waiter = nullptr;
267 return true;
268 }
269
270 // SurfaceView is already allocated.
271
272 if (iter->second.waiter != nullptr) {
DaleCurtis 2016/05/18 17:59:11 Can you explain this design choice? I.e. why would
liberato (no reviews please) 2016/05/18 18:49:39 because WMPI maintains at most one AVDA instance.
DaleCurtis 2016/05/18 18:55:49 Hmm, what about other WMPI instances?
liberato (no reviews please) 2016/05/18 19:51:18 |surface_id_| will not be the same if the surface
273 // Some other AVDA is waiting. |avda| will replace it, so notify it
274 // that it will fail.
275 iter->second.waiter->OnSurfaceAvailable(false);
276 iter->second.waiter = nullptr;
277 }
278
279 // |avda| is now waiting.
280 iter->second.waiter = avda;
281 return false;
282 }
283
284 // Clear any waiting request for |surface_id| by |avda|. It is okay if
285 // |waiter| is not waiting and/or isn't the owner of |surface_id|.
286 void DeallocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
287 SurfaceWaiterMap::iterator iter = surface_waiter_map_.find(surface_id);
288 if (iter == surface_waiter_map_.end())
DaleCurtis 2016/05/18 17:59:11 Should this dcheck?
liberato (no reviews please) 2016/05/18 18:49:39 no. this way, one simply calls Deallocate uncondi
289 return;
290
291 // If |avda| was waiting, then remove it without OnSurfaceAvailable.
292 if (iter->second.waiter == avda)
293 iter->second.waiter = nullptr;
294
295 // If |avda| is the owner, then let the next owner have it.
296 if (iter->second.owner == avda) {
DaleCurtis 2016/05/18 17:59:11 Use early returns instead.
liberato (no reviews please) 2016/05/18 18:49:39 Done.
297 if (AndroidVideoDecodeAccelerator* waiter = iter->second.waiter) {
298 // Promote |waiter| to be the owner.
299 iter->second.owner = waiter;
300 iter->second.waiter = nullptr;
301 waiter->OnSurfaceAvailable(true);
302 } else {
303 // No waiter -- remove the record and return since |iter| is
304 // no longer valid.
305 surface_waiter_map_.erase(iter);
306 return;
307 }
308 }
309 }
310
252 private: 311 private:
253 friend struct base::DefaultLazyInstanceTraits<AVDATimerManager>; 312 friend struct base::DefaultLazyInstanceTraits<AVDATimerManager>;
254 313
255 AVDATimerManager() : construction_thread_("AVDAThread") {} 314 AVDATimerManager() : construction_thread_("AVDAThread") {}
256 ~AVDATimerManager() { NOTREACHED(); } 315 ~AVDATimerManager() { NOTREACHED(); }
257 316
258 void RunTimer() { 317 void RunTimer() {
259 { 318 {
260 // Call out to all AVDA instances, some of which may attempt to remove 319 // Call out to all AVDA instances, some of which may attempt to remove
261 // themselves from the list during this operation; those removals will be 320 // themselves from the list during this operation; those removals will be
(...skipping 11 matching lines...) Expand all
273 // TODO(dalecurtis): We may want to consider chunking this if task execution 332 // TODO(dalecurtis): We may want to consider chunking this if task execution
274 // takes too long for the combined timer. 333 // takes too long for the combined timer.
275 } 334 }
276 335
277 // All AVDA instances that would like us to poll DoIOTask. 336 // All AVDA instances that would like us to poll DoIOTask.
278 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_; 337 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_;
279 338
280 // All AVDA instances that might like to use the construction thread. 339 // All AVDA instances that might like to use the construction thread.
281 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_; 340 std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_;
282 341
342 // [surface id] = accelerator that owns the surface, or nullptr.
watk 2016/05/18 20:38:18 Comment seems out of date/wrong place
liberato (no reviews please) 2016/05/18 21:13:13 Done.
343 struct OwnerRecord {
344 OwnerRecord() : owner(nullptr), waiter(nullptr) {}
DaleCurtis 2016/05/18 17:59:11 Constructor prevents this from being a POD type. I
liberato (no reviews please) 2016/05/18 18:49:39 hrm, i just tried brace-or-equal but that doesn't
DaleCurtis 2016/05/18 18:55:49 Dropping the constructor and not using = nullptr o
liberato (no reviews please) 2016/05/18 19:51:17 i switched to "= nullptr" in the most recent CL.
345 AndroidVideoDecodeAccelerator* owner;
346 AndroidVideoDecodeAccelerator* waiter;
347 };
348 using SurfaceWaiterMap = std::map<int, OwnerRecord>;
349 SurfaceWaiterMap surface_waiter_map_;
350
283 // Since we can't delete while iterating when using a set, defer erasure until 351 // Since we can't delete while iterating when using a set, defer erasure until
284 // after iteration complete. 352 // after iteration complete.
285 bool timer_running_ = false; 353 bool timer_running_ = false;
286 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; 354 std::set<AndroidVideoDecodeAccelerator*> pending_erase_;
287 355
288 // Repeating timer responsible for draining pending IO to the codecs. 356 // Repeating timer responsible for draining pending IO to the codecs.
289 base::RepeatingTimer io_timer_; 357 base::RepeatingTimer io_timer_;
290 358
291 base::Thread construction_thread_; 359 base::Thread construction_thread_;
292 360
(...skipping 18 matching lines...) Expand all
311 is_encrypted_(false), 379 is_encrypted_(false),
312 state_(NO_ERROR), 380 state_(NO_ERROR),
313 picturebuffers_requested_(false), 381 picturebuffers_requested_(false),
314 drain_type_(DRAIN_TYPE_NONE), 382 drain_type_(DRAIN_TYPE_NONE),
315 media_drm_bridge_cdm_context_(nullptr), 383 media_drm_bridge_cdm_context_(nullptr),
316 cdm_registration_id_(0), 384 cdm_registration_id_(0),
317 pending_input_buf_index_(-1), 385 pending_input_buf_index_(-1),
318 error_sequence_token_(0), 386 error_sequence_token_(0),
319 defer_errors_(false), 387 defer_errors_(false),
320 deferred_initialization_pending_(false), 388 deferred_initialization_pending_(false),
389 cdm_id_(0),
321 surface_id_(media::VideoDecodeAccelerator::Config::kNoSurfaceID), 390 surface_id_(media::VideoDecodeAccelerator::Config::kNoSurfaceID),
322 weak_this_factory_(this) {} 391 weak_this_factory_(this) {}
323 392
324 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 393 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
325 DCHECK(thread_checker_.CalledOnValidThread()); 394 DCHECK(thread_checker_.CalledOnValidThread());
326 g_avda_timer.Pointer()->StopTimer(this); 395 g_avda_timer.Pointer()->StopTimer(this);
327 g_avda_timer.Pointer()->StopThread(this); 396 g_avda_timer.Pointer()->StopThread(this);
328 397
329 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 398 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
330 if (!media_drm_bridge_cdm_context_) 399 if (!media_drm_bridge_cdm_context_)
(...skipping 21 matching lines...) Expand all
352 return false; 421 return false;
353 } 422 }
354 423
355 DCHECK(client); 424 DCHECK(client);
356 client_ = client; 425 client_ = client;
357 codec_config_ = new CodecConfig(); 426 codec_config_ = new CodecConfig();
358 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile); 427 codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile);
359 codec_config_->initial_expected_coded_size_ = 428 codec_config_->initial_expected_coded_size_ =
360 config.initial_expected_coded_size; 429 config.initial_expected_coded_size;
361 is_encrypted_ = config.is_encrypted; 430 is_encrypted_ = config.is_encrypted;
431 cdm_id_ = config.cdm_id;
362 432
363 // We signalled that we support deferred initialization, so see if the client 433 // We signalled that we support deferred initialization, so see if the client
364 // does also. 434 // does also.
365 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; 435 deferred_initialization_pending_ = config.is_deferred_initialization_allowed;
366 436
367 if (is_encrypted_ && !deferred_initialization_pending_) { 437 if (is_encrypted_ && !deferred_initialization_pending_) {
368 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams"; 438 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams";
369 return false; 439 return false;
370 } 440 }
371 441
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; 478 DVLOG(1) << __FUNCTION__ << ", using copy back strategy.";
409 strategy_.reset(new AndroidCopyingBackingStrategy(this)); 479 strategy_.reset(new AndroidCopyingBackingStrategy(this));
410 } 480 }
411 481
412 if (!make_context_current_cb_.Run()) { 482 if (!make_context_current_cb_.Run()) {
413 LOG(ERROR) << "Failed to make this decoder's GL context current."; 483 LOG(ERROR) << "Failed to make this decoder's GL context current.";
414 return false; 484 return false;
415 } 485 }
416 486
417 surface_id_ = config.surface_id; 487 surface_id_ = config.surface_id;
488 if (g_avda_timer.Pointer()->AllocateSurface(surface_id_, this)) {
489 // We have succesfully owned the surface, so finish initialization now.
490 return InitializeStrategy();
491 }
492
493 // We have to wait for some other AVDA instance to free up the surface.
494 // OnSurfaceAvailable will be called when it's available.
495 return true;
496 }
497
498 void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) {
499 DCHECK(deferred_initialization_pending_);
500
501 if (!success) {
502 // Surface isn't available and/or we're being destroyed.
503 NotifyInitializationComplete(false);
504 deferred_initialization_pending_ = false;
505 return;
506 }
507
508 if (!InitializeStrategy()) {
watk 2016/05/18 20:38:18 Could merge this block into the above with a || if
liberato (no reviews please) 2016/05/18 21:13:13 Done.
509 NotifyInitializationComplete(false);
510 deferred_initialization_pending_ = false;
511 }
512 }
513
514 bool AndroidVideoDecodeAccelerator::InitializeStrategy() {
418 codec_config_->surface_ = strategy_->Initialize(surface_id_); 515 codec_config_->surface_ = strategy_->Initialize(surface_id_);
419 if (codec_config_->surface_.IsEmpty()) { 516 if (codec_config_->surface_.IsEmpty()) {
420 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " 517 LOG(ERROR) << "Failed to initialize the backing strategy. The returned "
421 "Java surface is empty."; 518 "Java surface is empty.";
422 return false; 519 return false;
423 } 520 }
424 521
425 on_destroying_surface_cb_ = 522 on_destroying_surface_cb_ =
426 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface, 523 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface,
427 weak_this_factory_.GetWeakPtr()); 524 weak_this_factory_.GetWeakPtr());
(...skipping 10 matching lines...) Expand all
438 535
439 // Start the thread for async configuration, even if we don't need it now. 536 // Start the thread for async configuration, even if we don't need it now.
440 // ResetCodecState might rebuild the codec later, for example. 537 // ResetCodecState might rebuild the codec later, for example.
441 if (!g_avda_timer.Pointer()->StartThread(this)) { 538 if (!g_avda_timer.Pointer()->StartThread(this)) {
442 LOG(ERROR) << "Failed to start AVDA thread"; 539 LOG(ERROR) << "Failed to start AVDA thread";
443 return false; 540 return false;
444 } 541 }
445 542
446 // If we are encrypted, then we aren't able to create the codec yet. 543 // If we are encrypted, then we aren't able to create the codec yet.
447 if (is_encrypted_) { 544 if (is_encrypted_) {
448 InitializeCdm(config.cdm_id); 545 InitializeCdm();
449 return true; 546 return true;
450 } 547 }
451 548
452 if (deferred_initialization_pending_) { 549 if (deferred_initialization_pending_) {
453 ConfigureMediaCodecAsynchronously(); 550 ConfigureMediaCodecAsynchronously();
454 return true; 551 return true;
455 } 552 }
456 553
457 // If the client doesn't support deferred initialization (WebRTC), then we 554 // If the client doesn't support deferred initialization (WebRTC), then we
458 // should complete it now and return a meaningful result. 555 // should complete it now and return a meaningful result. Note that it would
556 // be nice if we didn't have to worry about starting codec configuration at
557 // all (::Initialize or the wrapper can do it), but then they have to remember
558 // not to start codec config if we have to wait for the cdm. It's somewhat
559 // clearer for us to handle both cases.
459 return ConfigureMediaCodecSynchronously(); 560 return ConfigureMediaCodecSynchronously();
460 } 561 }
461 562
462 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) { 563 void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) {
463 DCHECK(thread_checker_.CalledOnValidThread()); 564 DCHECK(thread_checker_.CalledOnValidThread());
464 TRACE_EVENT0("media", "AVDA::DoIOTask"); 565 TRACE_EVENT0("media", "AVDA::DoIOTask");
465 if (state_ == ERROR || state_ == WAITING_FOR_CODEC || 566 if (state_ == ERROR || state_ == WAITING_FOR_CODEC ||
466 state_ == SURFACE_DESTROYED) { 567 state_ == SURFACE_DESTROYED) {
467 return; 568 return;
468 } 569 }
(...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 1298
1198 void AndroidVideoDecodeAccelerator::ActualDestroy() { 1299 void AndroidVideoDecodeAccelerator::ActualDestroy() {
1199 DVLOG(1) << __FUNCTION__; 1300 DVLOG(1) << __FUNCTION__;
1200 DCHECK(thread_checker_.CalledOnValidThread()); 1301 DCHECK(thread_checker_.CalledOnValidThread());
1201 1302
1202 if (!on_destroying_surface_cb_.is_null()) { 1303 if (!on_destroying_surface_cb_.is_null()) {
1203 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback( 1304 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback(
1204 on_destroying_surface_cb_); 1305 on_destroying_surface_cb_);
1205 } 1306 }
1206 1307
1308 // We no longer care about |surface_id_|, in case we did before. It's okay
1309 // if we have no surface and/or weren't the owner or a waiter.
1310 g_avda_timer.Pointer()->DeallocateSurface(surface_id_, this);
1311
1207 // Note that async codec construction might still be in progress. In that 1312 // Note that async codec construction might still be in progress. In that
1208 // case, the codec will be deleted when it completes once we invalidate all 1313 // case, the codec will be deleted when it completes once we invalidate all
1209 // our weak refs. 1314 // our weak refs.
1210 weak_this_factory_.InvalidateWeakPtrs(); 1315 weak_this_factory_.InvalidateWeakPtrs();
1211 if (media_codec_) { 1316 if (media_codec_) {
1212 g_avda_timer.Pointer()->StopTimer(this); 1317 g_avda_timer.Pointer()->StopTimer(this);
1213 media_codec_.reset(); 1318 media_codec_.reset();
1214 } 1319 }
1215 delete this; 1320 delete this;
1216 } 1321 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1289 const ::tracked_objects::Location& from_here, 1394 const ::tracked_objects::Location& from_here,
1290 media::VideoDecodeAccelerator::Error error) { 1395 media::VideoDecodeAccelerator::Error error) {
1291 base::MessageLoop::current()->PostDelayedTask( 1396 base::MessageLoop::current()->PostDelayedTask(
1292 from_here, 1397 from_here,
1293 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, 1398 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError,
1294 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), 1399 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_),
1295 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); 1400 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta()));
1296 state_ = ERROR; 1401 state_ = ERROR;
1297 } 1402 }
1298 1403
1299 void AndroidVideoDecodeAccelerator::InitializeCdm(int cdm_id) { 1404 void AndroidVideoDecodeAccelerator::InitializeCdm() {
1300 DVLOG(2) << __FUNCTION__ << ": " << cdm_id; 1405 DVLOG(2) << __FUNCTION__ << ": " << cdm_id_;
1301 1406
1302 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 1407 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
1303 NOTIMPLEMENTED(); 1408 NOTIMPLEMENTED();
1304 NotifyInitializationComplete(false); 1409 NotifyInitializationComplete(false);
1305 #else 1410 #else
1306 // Store the CDM to hold a reference to it. 1411 // Store the CDM to hold a reference to it.
1307 cdm_for_reference_holding_only_ = media::MojoCdmService::LegacyGetCdm(cdm_id); 1412 cdm_for_reference_holding_only_ =
1413 media::MojoCdmService::LegacyGetCdm(cdm_id_);
1308 DCHECK(cdm_for_reference_holding_only_); 1414 DCHECK(cdm_for_reference_holding_only_);
1309 1415
1310 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext. 1416 // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext.
1311 media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>( 1417 media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>(
1312 cdm_for_reference_holding_only_->GetCdmContext()); 1418 cdm_for_reference_holding_only_->GetCdmContext());
1313 DCHECK(media_drm_bridge_cdm_context_); 1419 DCHECK(media_drm_bridge_cdm_context_);
1314 1420
1315 // Register CDM callbacks. The callbacks registered will be posted back to 1421 // Register CDM callbacks. The callbacks registered will be posted back to
1316 // this thread via BindToCurrentLoop. 1422 // this thread via BindToCurrentLoop.
1317 1423
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
1502 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { 1608 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) {
1503 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: 1609 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities::
1504 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; 1610 SUPPORTS_EXTERNAL_OUTPUT_SURFACE;
1505 } 1611 }
1506 } 1612 }
1507 1613
1508 return capabilities; 1614 return capabilities;
1509 } 1615 }
1510 1616
1511 } // namespace media 1617 } // namespace media
OLDNEW
« media/gpu/android_video_decode_accelerator.h ('K') | « 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