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

Side by Side 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 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 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 get_gles2_decoder_cb_(get_gles2_decoder_cb), 230 get_gles2_decoder_cb_(get_gles2_decoder_cb),
231 state_(NO_ERROR), 231 state_(NO_ERROR),
232 picturebuffers_requested_(false), 232 picturebuffers_requested_(false),
233 picture_buffer_manager_(this), 233 picture_buffer_manager_(this),
234 media_drm_bridge_cdm_context_(nullptr), 234 media_drm_bridge_cdm_context_(nullptr),
235 cdm_registration_id_(0), 235 cdm_registration_id_(0),
236 pending_input_buf_index_(-1), 236 pending_input_buf_index_(-1),
237 deferred_initialization_pending_(false), 237 deferred_initialization_pending_(false),
238 codec_needs_reset_(false), 238 codec_needs_reset_(false),
239 defer_surface_creation_(false), 239 defer_surface_creation_(false),
240 last_release_task_type_(TaskType::AUTO_CODEC),
240 weak_this_factory_(this) {} 241 weak_this_factory_(this) {}
241 242
242 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 243 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
243 DCHECK(thread_checker_.CalledOnValidThread()); 244 DCHECK(thread_checker_.CalledOnValidThread());
244 g_avda_manager.Get().StopTimer(this); 245 g_avda_manager.Get().StopTimer(this);
245 AVDACodecAllocator::Instance()->StopThread(this); 246 AVDACodecAllocator::Instance()->StopThread(this);
246 247
247 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 248 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
248 if (!media_drm_bridge_cdm_context_) 249 if (!media_drm_bridge_cdm_context_)
249 return; 250 return;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 } 360 }
360 361
361 bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() { 362 bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() {
362 if (!make_context_current_cb_.Run()) { 363 if (!make_context_current_cb_.Run()) {
363 LOG(ERROR) << "Failed to make this decoder's GL context current."; 364 LOG(ERROR) << "Failed to make this decoder's GL context current.";
364 return false; 365 return false;
365 } 366 }
366 367
367 codec_config_->surface = 368 codec_config_->surface =
368 picture_buffer_manager_.Initialize(config_.surface_id); 369 picture_buffer_manager_.Initialize(config_.surface_id);
370 codec_config_->surface_texture = picture_buffer_manager_.surface_texture();
369 if (codec_config_->surface.IsEmpty()) 371 if (codec_config_->surface.IsEmpty())
370 return false; 372 return false;
371 373
372 if (!AVDACodecAllocator::Instance()->StartThread(this)) 374 if (!AVDACodecAllocator::Instance()->StartThread(this))
373 return false; 375 return false;
374 376
375 // If we are encrypted, then we aren't able to create the codec yet. 377 // If we are encrypted, then we aren't able to create the codec yet.
376 if (config_.is_encrypted()) { 378 if (config_.is_encrypted()) {
377 InitializeCdm(); 379 InitializeCdm();
378 return true; 380 return true;
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 DCHECK(thread_checker_.CalledOnValidThread()); 868 DCHECK(thread_checker_.CalledOnValidThread());
867 StartCodecDrain(DRAIN_FOR_FLUSH); 869 StartCodecDrain(DRAIN_FOR_FLUSH);
868 } 870 }
869 871
870 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { 872 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() {
871 DCHECK(thread_checker_.CalledOnValidThread()); 873 DCHECK(thread_checker_.CalledOnValidThread());
872 874
873 DCHECK_NE(state_, WAITING_FOR_CODEC); 875 DCHECK_NE(state_, WAITING_FOR_CODEC);
874 state_ = WAITING_FOR_CODEC; 876 state_ = WAITING_FOR_CODEC;
875 877
876 if (media_codec_) { 878 ReleaseCodec();
877 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
878 std::move(media_codec_), codec_config_->task_type, config_.surface_id);
879 picture_buffer_manager_.CodecChanged(nullptr);
880 }
881 879
882 base::Optional<TaskType> task_type = 880 base::Optional<TaskType> task_type =
883 AVDACodecAllocator::Instance()->TaskTypeForAllocation(); 881 AVDACodecAllocator::Instance()->TaskTypeForAllocation();
884 if (!task_type) { 882 if (!task_type) {
885 // If there is no free thread, then just fail. 883 // If there is no free thread, then just fail.
886 OnCodecConfigured(nullptr); 884 OnCodecConfigured(nullptr);
887 return; 885 return;
888 } 886 }
889 887
890 // If autodetection is disallowed, fall back to Chrome's software decoders 888 // If autodetection is disallowed, fall back to Chrome's software decoders
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1135 1133
1136 void AndroidVideoDecodeAccelerator::ActualDestroy() { 1134 void AndroidVideoDecodeAccelerator::ActualDestroy() {
1137 DVLOG(1) << __func__; 1135 DVLOG(1) << __func__;
1138 DCHECK(thread_checker_.CalledOnValidThread()); 1136 DCHECK(thread_checker_.CalledOnValidThread());
1139 1137
1140 // Note that async codec construction might still be in progress. In that 1138 // Note that async codec construction might still be in progress. In that
1141 // case, the codec will be deleted when it completes once we invalidate all 1139 // case, the codec will be deleted when it completes once we invalidate all
1142 // our weak refs. 1140 // our weak refs.
1143 weak_this_factory_.InvalidateWeakPtrs(); 1141 weak_this_factory_.InvalidateWeakPtrs();
1144 g_avda_manager.Get().StopTimer(this); 1142 g_avda_manager.Get().StopTimer(this);
1145 if (media_codec_) { 1143 ReleaseCodec();
1146 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1147 std::move(media_codec_), codec_config_->task_type, config_.surface_id);
1148 }
1149 1144
1150 // We no longer care about |surface_id|, in case we did before. It's okay 1145 // We no longer care about |surface_id|, in case we did before. It's okay
1151 // if we have no surface and/or weren't the owner or a waiter. 1146 // if we have no surface and/or weren't the owner or a waiter.
1152 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id); 1147 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id);
1153 1148
1149 // Hop the SurfaceTexture release call through the task runner used last time
1150 // we released a codec. This ensures that we release the surface texture after
1151 // the codec it's attached to (if any) is released. It's not sufficient to use
1152 // |codec_config_->task_type| because that might have changed since we
1153 // released the codec this surface was attached to.
1154 if (codec_config_->surface_texture) {
watk 2017/01/17 19:02:48 This is where surface_texture is used. We store a
1155 AVDACodecAllocator::Instance()
1156 ->TaskRunnerFor(last_release_task_type_)
1157 ->PostTaskAndReply(
1158 FROM_HERE, base::Bind(&base::DoNothing),
1159 base::Bind(&gl::SurfaceTexture::ReleaseSurfaceTexture,
1160 codec_config_->surface_texture));
1161 }
1162
1154 delete this; 1163 delete this;
1155 } 1164 }
1156 1165
1157 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( 1166 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
1158 const base::WeakPtr<Client>& decode_client, 1167 const base::WeakPtr<Client>& decode_client,
1159 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { 1168 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
1160 return false; 1169 return false;
1161 } 1170 }
1162 1171
1163 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { 1172 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const {
(...skipping 27 matching lines...) Expand all
1191 1200
1192 pending_surface_id_ = SurfaceManager::kNoSurfaceID; 1201 pending_surface_id_ = SurfaceManager::kNoSurfaceID;
1193 UpdateSurface(); 1202 UpdateSurface();
1194 return; 1203 return;
1195 } 1204 }
1196 1205
1197 // If we're currently asynchronously configuring a codec, it will be destroyed 1206 // If we're currently asynchronously configuring a codec, it will be destroyed
1198 // when configuration completes and it notices that |state_| has changed to 1207 // when configuration completes and it notices that |state_| has changed to
1199 // SURFACE_DESTROYED. 1208 // SURFACE_DESTROYED.
1200 state_ = SURFACE_DESTROYED; 1209 state_ = SURFACE_DESTROYED;
1201 if (media_codec_) { 1210 ReleaseCodec();
1202 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1203 std::move(media_codec_), codec_config_->task_type, config_.surface_id);
1204 picture_buffer_manager_.CodecChanged(nullptr);
1205 }
1206 1211
1207 // If we're draining, signal completion now because the drain can no longer 1212 // If we're draining, signal completion now because the drain can no longer
1208 // proceed. 1213 // proceed.
1209 if (drain_type_) 1214 if (drain_type_)
1210 OnDrainCompleted(); 1215 OnDrainCompleted();
1211 } 1216 }
1212 1217
1213 void AndroidVideoDecodeAccelerator::InitializeCdm() { 1218 void AndroidVideoDecodeAccelerator::InitializeCdm() {
1214 DVLOG(2) << __func__ << ": " << config_.cdm_id; 1219 DVLOG(2) << __func__ << ": " << config_.cdm_id;
1215 1220
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
1459 1464
1460 // Ensure the current context is active when switching surfaces; we may need 1465 // Ensure the current context is active when switching surfaces; we may need
1461 // to create a new texture. 1466 // to create a new texture.
1462 if (success && !make_context_current_cb_.Run()) { 1467 if (success && !make_context_current_cb_.Run()) {
1463 NOTIFY_ERROR(PLATFORM_FAILURE, 1468 NOTIFY_ERROR(PLATFORM_FAILURE,
1464 "Failed to make this decoder's GL context current when " 1469 "Failed to make this decoder's GL context current when "
1465 "switching surfaces."); 1470 "switching surfaces.");
1466 success = false; 1471 success = false;
1467 } 1472 }
1468 1473
1474 gl::ScopedJavaSurface new_surface;
1469 if (success) { 1475 if (success) {
1470 codec_config_->surface = picture_buffer_manager_.Initialize(new_surface_id); 1476 new_surface = picture_buffer_manager_.Initialize(new_surface_id);
1471 if (codec_config_->surface.IsEmpty()) { 1477 if (new_surface.IsEmpty()) {
1472 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces."); 1478 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces.");
1473 success = false; 1479 success = false;
1474 } 1480 }
1475 } 1481 }
1476 1482
1477 if (success && media_codec_ && 1483 if (success && media_codec_ &&
1478 !media_codec_->SetSurface(codec_config_->surface.j_surface().obj())) { 1484 !media_codec_->SetSurface(new_surface.j_surface().obj())) {
1479 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces."); 1485 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces.");
1480 success = false; 1486 success = false;
1481 } 1487 }
1482 1488
1483 if (success) { 1489 if (success) {
1484 config_.surface_id = new_surface_id; 1490 config_.surface_id = new_surface_id;
1491 codec_config_->surface = std::move(new_surface);
1492 codec_config_->surface_texture = picture_buffer_manager_.surface_texture();
1485 } else { 1493 } else {
1486 // This might be called from OnSurfaceDestroyed(), so we have to release the 1494 // This might be called from OnSurfaceDestroyed(), so we have to release the
1487 // MediaCodec if we failed to switch the surface. 1495 // MediaCodec if we failed to switch the surface.
1488 if (media_codec_) { 1496 ReleaseCodec();
1489 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1490 std::move(media_codec_), codec_config_->task_type,
1491 previous_surface_id);
1492 picture_buffer_manager_.CodecChanged(nullptr);
1493 }
1494 AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id); 1497 AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id);
1495 } 1498 }
1496 1499
1497 // Regardless of whether we succeeded, we no longer own the previous surface. 1500 // Regardless of whether we succeeded, we no longer own the previous surface.
1498 AVDACodecAllocator::Instance()->DeallocateSurface(this, previous_surface_id); 1501 AVDACodecAllocator::Instance()->DeallocateSurface(this, previous_surface_id);
1499 1502
1500 return success; 1503 return success;
1501 } 1504 }
1502 1505
1506 void AndroidVideoDecodeAccelerator::ReleaseCodec() {
1507 if (!media_codec_)
1508 return;
1509
1510 picture_buffer_manager_.CodecChanged(nullptr);
1511 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1512 std::move(media_codec_), codec_config_->task_type, config_.surface_id);
1513 last_release_task_type_ = codec_config_->task_type;
1514 }
1515
1503 } // namespace media 1516 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698