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

Unified Diff: media/gpu/android_video_decode_accelerator.cc

Issue 2629223003: media: Ensure MediaCodecs are released before attached SurfaceTextures (Closed)
Patch Set: more comments 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 side-by-side diff with in-line comments
Download patch
Index: media/gpu/android_video_decode_accelerator.cc
diff --git a/media/gpu/android_video_decode_accelerator.cc b/media/gpu/android_video_decode_accelerator.cc
index 16d347983ebd17cc4c3ef193c0c865998703b536..c907c601f4d42be09997250050166ca3465d13e3 100644
--- a/media/gpu/android_video_decode_accelerator.cc
+++ b/media/gpu/android_video_decode_accelerator.cc
@@ -237,6 +237,7 @@ AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator(
deferred_initialization_pending_(false),
codec_needs_reset_(false),
defer_surface_creation_(false),
+ last_release_task_type_(TaskType::AUTO_CODEC),
weak_this_factory_(this) {}
AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
@@ -366,6 +367,7 @@ bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() {
codec_config_->surface =
picture_buffer_manager_.Initialize(config_.surface_id);
+ codec_config_->surface_texture = picture_buffer_manager_.surface_texture();
if (codec_config_->surface.IsEmpty())
return false;
@@ -873,11 +875,7 @@ void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() {
DCHECK_NE(state_, WAITING_FOR_CODEC);
state_ = WAITING_FOR_CODEC;
- if (media_codec_) {
- AVDACodecAllocator::Instance()->ReleaseMediaCodec(
- std::move(media_codec_), codec_config_->task_type, config_.surface_id);
- picture_buffer_manager_.CodecChanged(nullptr);
- }
+ ReleaseCodec();
base::Optional<TaskType> task_type =
AVDACodecAllocator::Instance()->TaskTypeForAllocation();
@@ -1142,15 +1140,26 @@ void AndroidVideoDecodeAccelerator::ActualDestroy() {
// our weak refs.
weak_this_factory_.InvalidateWeakPtrs();
g_avda_manager.Get().StopTimer(this);
- if (media_codec_) {
- AVDACodecAllocator::Instance()->ReleaseMediaCodec(
- std::move(media_codec_), codec_config_->task_type, config_.surface_id);
- }
+ ReleaseCodec();
// We no longer care about |surface_id|, in case we did before. It's okay
// if we have no surface and/or weren't the owner or a waiter.
AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id);
+ // Hop the SurfaceTexture release call through the task runner used last time
+ // we released a codec. This ensures that we release the surface texture after
+ // the codec it's attached to (if any) is released. It's not sufficient to use
+ // |codec_config_->task_type| because that might have changed since we
+ // released the codec this surface was attached to.
+ if (codec_config_->surface_texture) {
watk 2017/01/17 19:02:48 This is where surface_texture is used. We store a
+ AVDACodecAllocator::Instance()
+ ->TaskRunnerFor(last_release_task_type_)
+ ->PostTaskAndReply(
+ FROM_HERE, base::Bind(&base::DoNothing),
+ base::Bind(&gl::SurfaceTexture::ReleaseSurfaceTexture,
+ codec_config_->surface_texture));
+ }
+
delete this;
}
@@ -1198,11 +1207,7 @@ void AndroidVideoDecodeAccelerator::OnSurfaceDestroyed() {
// when configuration completes and it notices that |state_| has changed to
// SURFACE_DESTROYED.
state_ = SURFACE_DESTROYED;
- if (media_codec_) {
- AVDACodecAllocator::Instance()->ReleaseMediaCodec(
- std::move(media_codec_), codec_config_->task_type, config_.surface_id);
- picture_buffer_manager_.CodecChanged(nullptr);
- }
+ ReleaseCodec();
// If we're draining, signal completion now because the drain can no longer
// proceed.
@@ -1466,31 +1471,29 @@ bool AndroidVideoDecodeAccelerator::UpdateSurface() {
success = false;
}
+ gl::ScopedJavaSurface new_surface;
if (success) {
- codec_config_->surface = picture_buffer_manager_.Initialize(new_surface_id);
- if (codec_config_->surface.IsEmpty()) {
+ new_surface = picture_buffer_manager_.Initialize(new_surface_id);
+ if (new_surface.IsEmpty()) {
NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces.");
success = false;
}
}
if (success && media_codec_ &&
- !media_codec_->SetSurface(codec_config_->surface.j_surface().obj())) {
+ !media_codec_->SetSurface(new_surface.j_surface().obj())) {
NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces.");
success = false;
}
if (success) {
config_.surface_id = new_surface_id;
+ codec_config_->surface = std::move(new_surface);
+ codec_config_->surface_texture = picture_buffer_manager_.surface_texture();
} else {
// This might be called from OnSurfaceDestroyed(), so we have to release the
// MediaCodec if we failed to switch the surface.
- if (media_codec_) {
- AVDACodecAllocator::Instance()->ReleaseMediaCodec(
- std::move(media_codec_), codec_config_->task_type,
- previous_surface_id);
- picture_buffer_manager_.CodecChanged(nullptr);
- }
+ ReleaseCodec();
AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id);
}
@@ -1500,4 +1503,14 @@ bool AndroidVideoDecodeAccelerator::UpdateSurface() {
return success;
}
+void AndroidVideoDecodeAccelerator::ReleaseCodec() {
+ if (!media_codec_)
+ return;
+
+ picture_buffer_manager_.CodecChanged(nullptr);
+ AVDACodecAllocator::Instance()->ReleaseMediaCodec(
+ std::move(media_codec_), codec_config_->task_type, config_.surface_id);
+ last_release_task_type_ = codec_config_->task_type;
+}
+
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698