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

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

Issue 2508053002: media: Do a TimedWait() for video surface teardown in AVDA (Closed)
Patch Set: change timeout to 2 Created 4 years 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') | media/gpu/avda_codec_allocator.h » ('j') | 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 // pictures have been fed to saturate any internal buffering). This is 99 // pictures have been fed to saturate any internal buffering). This is
100 // speculative and it's unclear that this would be a win (nor that there's a 100 // speculative and it's unclear that this would be a win (nor that there's a
101 // reasonably device-agnostic way to fill in the "believes" above). 101 // reasonably device-agnostic way to fill in the "believes" above).
102 constexpr base::TimeDelta DecodePollDelay = 102 constexpr base::TimeDelta DecodePollDelay =
103 base::TimeDelta::FromMilliseconds(10); 103 base::TimeDelta::FromMilliseconds(10);
104 104
105 constexpr base::TimeDelta NoWaitTimeOut = base::TimeDelta::FromMicroseconds(0); 105 constexpr base::TimeDelta NoWaitTimeOut = base::TimeDelta::FromMicroseconds(0);
106 106
107 constexpr base::TimeDelta IdleTimerTimeOut = base::TimeDelta::FromSeconds(1); 107 constexpr base::TimeDelta IdleTimerTimeOut = base::TimeDelta::FromSeconds(1);
108 108
109 // On low end devices (< KitKat is always low-end due to buggy MediaCodec),
110 // defer the surface creation until the codec is actually used if we know no
111 // software fallback exists.
112 bool ShouldDeferSurfaceCreation(int surface_id, VideoCodec codec) {
113 return surface_id == SurfaceManager::kNoSurfaceID && codec == kCodecH264 &&
114 AVDACodecAllocator::Instance()->IsAnyRegisteredAVDA() &&
115 (base::android::BuildInfo::GetInstance()->sdk_int() <= 18 ||
116 base::SysInfo::IsLowEndDevice());
117 }
118
109 } // namespace 119 } // namespace
110 120
111 static base::LazyInstance<AVDACodecAllocator>::Leaky g_avda_codec_allocator =
112 LAZY_INSTANCE_INITIALIZER;
113
114 // AVDAManager manages shared resources for a number of AVDA instances. 121 // AVDAManager manages shared resources for a number of AVDA instances.
115 // Its responsibilities include: 122 // Its responsibilities include:
116 // - Starting and stopping a shared "construction" thread for instantiating and 123 // - Starting and stopping a shared "construction" thread for instantiating and
117 // releasing MediaCodecs. 124 // releasing MediaCodecs.
118 // - Detecting when a task has hung on the construction thread so AVDAs can 125 // - Detecting when a task has hung on the construction thread so AVDAs can
119 // stop using it. 126 // stop using it.
120 // - Running a RepeatingTimer so that AVDAs can get a regular callback to 127 // - Running a RepeatingTimer so that AVDAs can get a regular callback to
121 // DoIOTask(). 128 // DoIOTask().
122 // - Tracking the allocation of surfaces to AVDAs and delivering callbacks when 129 // - Tracking the allocation of surfaces to AVDAs and delivering callbacks when
123 // surfaces are released. 130 // surfaces are released.
(...skipping 27 matching lines...) Expand all
151 if (timer_running_) { 158 if (timer_running_) {
152 pending_erase_.insert(avda); 159 pending_erase_.insert(avda);
153 return; 160 return;
154 } 161 }
155 162
156 timer_avda_instances_.erase(avda); 163 timer_avda_instances_.erase(avda);
157 if (timer_avda_instances_.empty()) 164 if (timer_avda_instances_.empty())
158 io_timer_.Stop(); 165 io_timer_.Stop();
159 } 166 }
160 167
161 // |avda| would like to use |surface_id|. If it is not busy, then mark it
162 // as busy and return true. If it is busy, then replace any existing waiter,
163 // make |avda| the current waiter, and return false. Any existing waiter
164 // is assumed to be on the way out, so we fail its allocation request.
165 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
166 // Nobody has to wait for no surface.
167 if (surface_id == SurfaceManager::kNoSurfaceID)
168 return true;
169
170 auto iter = surface_waiter_map_.find(surface_id);
171 if (iter == surface_waiter_map_.end()) {
172 // SurfaceView isn't allocated. Succeed.
173 surface_waiter_map_[surface_id].owner = avda;
174 return true;
175 }
176
177 // SurfaceView is already allocated.
178 if (iter->second.waiter) {
179 // Some other AVDA is waiting. |avda| will replace it, so notify it
180 // that it will fail.
181 iter->second.waiter->OnSurfaceAvailable(false);
182 iter->second.waiter = nullptr;
183 }
184
185 // |avda| is now waiting.
186 iter->second.waiter = avda;
187 return false;
188 }
189
190 // Clear any waiting request for |surface_id| by |avda|. It is okay if
191 // |waiter| is not waiting and/or isn't the owner of |surface_id|.
192 void DeallocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
193 SurfaceWaiterMap::iterator iter = surface_waiter_map_.find(surface_id);
194 if (iter == surface_waiter_map_.end())
195 return;
196
197 // If |avda| was waiting, then remove it without OnSurfaceAvailable.
198 if (iter->second.waiter == avda)
199 iter->second.waiter = nullptr;
200
201 // If |avda| is the owner, then let the waiter have it.
202 if (iter->second.owner != avda)
203 return;
204
205 AndroidVideoDecodeAccelerator* waiter = iter->second.waiter;
206 if (!waiter) {
207 // No waiter -- remove the record and return explicitly since |iter| is
208 // no longer valid.
209 surface_waiter_map_.erase(iter);
210 return;
211 }
212
213 // Promote |waiter| to be the owner.
214 iter->second.owner = waiter;
215 iter->second.waiter = nullptr;
216 waiter->OnSurfaceAvailable(true);
217 }
218
219 // On low end devices (< KitKat is always low-end due to buggy MediaCodec),
220 // defer the surface creation until the codec is actually used if we know no
221 // software fallback exists.
222 bool ShouldDeferSurfaceCreation(int surface_id, VideoCodec codec) {
223 return surface_id == SurfaceManager::kNoSurfaceID && codec == kCodecH264 &&
224 g_avda_codec_allocator.Get().IsAnyRegisteredAVDA() &&
225 (base::android::BuildInfo::GetInstance()->sdk_int() <= 18 ||
226 base::SysInfo::IsLowEndDevice());
227 }
228
229 private: 168 private:
230 friend struct base::DefaultLazyInstanceTraits<AVDAManager>; 169 friend struct base::DefaultLazyInstanceTraits<AVDAManager>;
231 170
232 AVDAManager() {} 171 AVDAManager() {}
233 ~AVDAManager() { NOTREACHED(); } 172 ~AVDAManager() { NOTREACHED(); }
234 173
235 void RunTimer() { 174 void RunTimer() {
236 { 175 {
237 // Call out to all AVDA instances, some of which may attempt to remove 176 // Call out to all AVDA instances, some of which may attempt to remove
238 // themselves from the list during this operation; those removals will be 177 // themselves from the list during this operation; those removals will be
239 // deferred until after all iterations are complete. 178 // deferred until after all iterations are complete.
240 base::AutoReset<bool> scoper(&timer_running_, true); 179 base::AutoReset<bool> scoper(&timer_running_, true);
241 for (auto* avda : timer_avda_instances_) 180 for (auto* avda : timer_avda_instances_)
242 avda->DoIOTask(false); 181 avda->DoIOTask(false);
243 } 182 }
244 183
245 // Take care of any deferred erasures. 184 // Take care of any deferred erasures.
246 for (auto* avda : pending_erase_) 185 for (auto* avda : pending_erase_)
247 StopTimer(avda); 186 StopTimer(avda);
248 pending_erase_.clear(); 187 pending_erase_.clear();
249 188
250 // TODO(dalecurtis): We may want to consider chunking this if task execution 189 // TODO(dalecurtis): We may want to consider chunking this if task execution
251 // takes too long for the combined timer. 190 // takes too long for the combined timer.
252 } 191 }
253 192
254 // All AVDA instances that would like us to poll DoIOTask. 193 // All AVDA instances that would like us to poll DoIOTask.
255 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_; 194 std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_;
256 195
257 struct OwnerRecord {
258 AndroidVideoDecodeAccelerator* owner = nullptr;
259 AndroidVideoDecodeAccelerator* waiter = nullptr;
260 };
261 // [surface id] = OwnerRecord for that surface.
262 using SurfaceWaiterMap = std::map<int, OwnerRecord>;
263 SurfaceWaiterMap surface_waiter_map_;
264
265 // Since we can't delete while iterating when using a set, defer erasure until 196 // Since we can't delete while iterating when using a set, defer erasure until
266 // after iteration complete. 197 // after iteration complete.
267 bool timer_running_ = false; 198 bool timer_running_ = false;
268 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; 199 std::set<AndroidVideoDecodeAccelerator*> pending_erase_;
269 200
270 // Repeating timer responsible for draining pending IO to the codecs. 201 // Repeating timer responsible for draining pending IO to the codecs.
271 base::RepeatingTimer io_timer_; 202 base::RepeatingTimer io_timer_;
272 203
273 base::ThreadChecker thread_checker_; 204 base::ThreadChecker thread_checker_;
274 205
275 DISALLOW_COPY_AND_ASSIGN(AVDAManager); 206 DISALLOW_COPY_AND_ASSIGN(AVDAManager);
276 }; 207 };
277 208
278 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager = 209 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager =
279 LAZY_INSTANCE_INITIALIZER; 210 LAZY_INSTANCE_INITIALIZER;
280 211
281 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {}
282
283 AndroidVideoDecodeAccelerator::CodecConfig::~CodecConfig() {}
284
285 AndroidVideoDecodeAccelerator::BitstreamRecord::BitstreamRecord( 212 AndroidVideoDecodeAccelerator::BitstreamRecord::BitstreamRecord(
286 const BitstreamBuffer& bitstream_buffer) 213 const BitstreamBuffer& bitstream_buffer)
287 : buffer(bitstream_buffer) { 214 : buffer(bitstream_buffer) {
288 if (buffer.id() != -1) 215 if (buffer.id() != -1)
289 memory.reset(new SharedMemoryRegion(buffer, true)); 216 memory.reset(new SharedMemoryRegion(buffer, true));
290 } 217 }
291 218
292 AndroidVideoDecodeAccelerator::BitstreamRecord::BitstreamRecord( 219 AndroidVideoDecodeAccelerator::BitstreamRecord::BitstreamRecord(
293 BitstreamRecord&& other) 220 BitstreamRecord&& other)
294 : buffer(std::move(other.buffer)), memory(std::move(other.memory)) {} 221 : buffer(std::move(other.buffer)), memory(std::move(other.memory)) {}
(...skipping 14 matching lines...) Expand all
309 cdm_registration_id_(0), 236 cdm_registration_id_(0),
310 pending_input_buf_index_(-1), 237 pending_input_buf_index_(-1),
311 deferred_initialization_pending_(false), 238 deferred_initialization_pending_(false),
312 codec_needs_reset_(false), 239 codec_needs_reset_(false),
313 defer_surface_creation_(false), 240 defer_surface_creation_(false),
314 weak_this_factory_(this) {} 241 weak_this_factory_(this) {}
315 242
316 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { 243 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
317 DCHECK(thread_checker_.CalledOnValidThread()); 244 DCHECK(thread_checker_.CalledOnValidThread());
318 g_avda_manager.Get().StopTimer(this); 245 g_avda_manager.Get().StopTimer(this);
319 g_avda_codec_allocator.Get().StopThread(this); 246 AVDACodecAllocator::Instance()->StopThread(this);
320 247
321 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 248 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
322 if (!media_drm_bridge_cdm_context_) 249 if (!media_drm_bridge_cdm_context_)
323 return; 250 return;
324 251
325 DCHECK(cdm_registration_id_); 252 DCHECK(cdm_registration_id_);
326 253
327 // Cancel previously registered callback (if any). 254 // Cancel previously registered callback (if any).
328 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB( 255 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(
329 MediaDrmBridgeCdmContext::MediaCryptoReadyCB()); 256 MediaDrmBridgeCdmContext::MediaCryptoReadyCB());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 DLOG(ERROR) << "Failed to get gles2 decoder instance."; 315 DLOG(ERROR) << "Failed to get gles2 decoder instance.";
389 return false; 316 return false;
390 } 317 }
391 318
392 // SetSurface() can't be called before Initialize(), so we pick up our first 319 // SetSurface() can't be called before Initialize(), so we pick up our first
393 // surface ID from the codec configuration. 320 // surface ID from the codec configuration.
394 DCHECK(!pending_surface_id_); 321 DCHECK(!pending_surface_id_);
395 322
396 // If we're low on resources, we may decide to defer creation of the surface 323 // If we're low on resources, we may decide to defer creation of the surface
397 // until the codec is actually used. 324 // until the codec is actually used.
398 if (g_avda_manager.Get().ShouldDeferSurfaceCreation(config_.surface_id, 325 if (ShouldDeferSurfaceCreation(config_.surface_id, codec_config_->codec_)) {
399 codec_config_->codec_)) {
400 DCHECK(!deferred_initialization_pending_); 326 DCHECK(!deferred_initialization_pending_);
401
402 // We should never be here if a SurfaceView is required. 327 // We should never be here if a SurfaceView is required.
403 DCHECK_EQ(config_.surface_id, SurfaceManager::kNoSurfaceID); 328 DCHECK_EQ(config_.surface_id, SurfaceManager::kNoSurfaceID);
404 DCHECK(g_avda_manager.Get().AllocateSurface(config_.surface_id, this));
405
406 defer_surface_creation_ = true; 329 defer_surface_creation_ = true;
407 NotifyInitializationComplete(true); 330 NotifyInitializationComplete(true);
408 return true; 331 return true;
409 } 332 }
410 333
411 // We signaled that we support deferred initialization, so see if the client 334 // We signaled that we support deferred initialization, so see if the client
412 // does also. 335 // does also.
413 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; 336 deferred_initialization_pending_ = config.is_deferred_initialization_allowed;
414 if (config_.is_encrypted && !deferred_initialization_pending_) { 337 if (config_.is_encrypted && !deferred_initialization_pending_) {
415 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams"; 338 DLOG(ERROR) << "Deferred initialization must be used for encrypted streams";
416 return false; 339 return false;
417 } 340 }
418 341
419 if (g_avda_manager.Get().AllocateSurface(config_.surface_id, this)) { 342 if (AVDACodecAllocator::Instance()->AllocateSurface(this,
420 // We have successfully owned the surface, so finish initialization now. 343 config_.surface_id)) {
344 // We now own the surface, so finish initialization.
421 return InitializePictureBufferManager(); 345 return InitializePictureBufferManager();
422 } 346 }
423 347
424 // We have to wait for some other AVDA instance to free up the surface. 348 // We have to wait for some other AVDA instance to free up the surface.
425 // OnSurfaceAvailable will be called when it's available. 349 // OnSurfaceAvailable will be called when it's available.
426 return true; 350 return true;
427 } 351 }
428 352
429 void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) { 353 void AndroidVideoDecodeAccelerator::OnSurfaceAvailable(bool success) {
430 DCHECK(deferred_initialization_pending_); 354 DCHECK(deferred_initialization_pending_);
431 DCHECK(!defer_surface_creation_); 355 DCHECK(!defer_surface_creation_);
432 356
433 if (!success || !InitializePictureBufferManager()) { 357 if (!success || !InitializePictureBufferManager()) {
434 NotifyInitializationComplete(false); 358 NotifyInitializationComplete(false);
435 deferred_initialization_pending_ = false; 359 deferred_initialization_pending_ = false;
436 } 360 }
437 } 361 }
438 362
439 bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() { 363 bool AndroidVideoDecodeAccelerator::InitializePictureBufferManager() {
440 if (!make_context_current_cb_.Run()) { 364 if (!make_context_current_cb_.Run()) {
441 LOG(ERROR) << "Failed to make this decoder's GL context current."; 365 LOG(ERROR) << "Failed to make this decoder's GL context current.";
442 return false; 366 return false;
443 } 367 }
444 368
445 codec_config_->surface_ = 369 codec_config_->surface_ =
446 picture_buffer_manager_.Initialize(config_.surface_id); 370 picture_buffer_manager_.Initialize(config_.surface_id);
447 if (codec_config_->surface_.IsEmpty()) 371 if (codec_config_->surface_.IsEmpty())
448 return false; 372 return false;
449 373
450 on_destroying_surface_cb_ = 374 if (!AVDACodecAllocator::Instance()->StartThread(this))
451 base::Bind(&AndroidVideoDecodeAccelerator::OnDestroyingSurface,
452 weak_this_factory_.GetWeakPtr());
453 AVDASurfaceTracker::GetInstance()->RegisterOnDestroyingSurfaceCallback(
454 on_destroying_surface_cb_);
455
456 if (!g_avda_codec_allocator.Get().StartThread(this))
457 return false; 375 return false;
458 376
459 // 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.
460 if (config_.is_encrypted) { 378 if (config_.is_encrypted) {
461 InitializeCdm(); 379 InitializeCdm();
462 return true; 380 return true;
463 } 381 }
464 382
465 if (deferred_initialization_pending_ || defer_surface_creation_) { 383 if (deferred_initialization_pending_ || defer_surface_creation_) {
466 defer_surface_creation_ = false; 384 defer_surface_creation_ = false;
(...skipping 483 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 868
951 if (state_ == SURFACE_DESTROYED || defer_surface_creation_) 869 if (state_ == SURFACE_DESTROYED || defer_surface_creation_)
952 NotifyFlushDone(); 870 NotifyFlushDone();
953 else 871 else
954 StartCodecDrain(DRAIN_FOR_FLUSH); 872 StartCodecDrain(DRAIN_FOR_FLUSH);
955 } 873 }
956 874
957 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() { 875 void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() {
958 DCHECK(thread_checker_.CalledOnValidThread()); 876 DCHECK(thread_checker_.CalledOnValidThread());
959 877
960 // It's probably okay just to return here, since the codec will be configured
961 // asynchronously. It's unclear that any state for the new request could
962 // be different, unless somebody modifies |codec_config_| while we're already
963 // waiting for a codec. One shouldn't do that for thread safety.
964 DCHECK_NE(state_, WAITING_FOR_CODEC); 878 DCHECK_NE(state_, WAITING_FOR_CODEC);
965
966 state_ = WAITING_FOR_CODEC; 879 state_ = WAITING_FOR_CODEC;
967 880
968 // Tell the picture buffer manager that we're changing codecs. The codec
969 // itself could be used normally, since we don't replace it until we're back
970 // on the main thread. However, if we're using an output surface, then the
971 // incoming codec might access that surface while the main thread is drawing.
972 // Telling the manager to forget the codec avoids this.
973 if (media_codec_) { 881 if (media_codec_) {
974 ReleaseMediaCodec(); 882 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
883 std::move(media_codec_), codec_config_->task_type_, config_.surface_id);
975 picture_buffer_manager_.CodecChanged(nullptr); 884 picture_buffer_manager_.CodecChanged(nullptr);
976 } 885 }
977 886
978 codec_config_->task_type_ = 887 codec_config_->task_type_ =
979 g_avda_codec_allocator.Get().TaskTypeForAllocation(); 888 AVDACodecAllocator::Instance()->TaskTypeForAllocation();
980 if (codec_config_->task_type_ == AVDACodecAllocator::TaskType::FAILED_CODEC) { 889 if (codec_config_->task_type_ == TaskType::FAILED_CODEC) {
981 // If there is no free thread, then just fail. 890 // If there is no free thread, then just fail.
982 OnCodecConfigured(nullptr); 891 OnCodecConfigured(nullptr);
983 return; 892 return;
984 } 893 }
985 894
986 // If autodetection is disallowed, fall back to Chrome's software decoders 895 // If autodetection is disallowed, fall back to Chrome's software decoders
987 // instead of using the software decoders provided by MediaCodec. 896 // instead of using the software decoders provided by MediaCodec.
988 if (codec_config_->task_type_ == AVDACodecAllocator::TaskType::SW_CODEC && 897 if (codec_config_->task_type_ == TaskType::SW_CODEC &&
989 IsMediaCodecSoftwareDecodingForbidden()) { 898 IsMediaCodecSoftwareDecodingForbidden()) {
990 OnCodecConfigured(nullptr); 899 OnCodecConfigured(nullptr);
991 return; 900 return;
992 } 901 }
993 902
994 base::PostTaskAndReplyWithResult( 903 AVDACodecAllocator::Instance()->CreateMediaCodecAsync(
995 g_avda_codec_allocator.Get() 904 weak_this_factory_.GetWeakPtr(), codec_config_);
996 .TaskRunnerFor(codec_config_->task_type_)
997 .get(),
998 FROM_HERE,
999 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread,
1000 codec_config_),
1001 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured,
1002 weak_this_factory_.GetWeakPtr()));
1003 } 905 }
1004 906
1005 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() { 907 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() {
908 DCHECK(thread_checker_.CalledOnValidThread());
909 DCHECK(!media_codec_);
910 DCHECK_NE(state_, WAITING_FOR_CODEC);
1006 state_ = WAITING_FOR_CODEC; 911 state_ = WAITING_FOR_CODEC;
1007 912
1008 ReleaseMediaCodec();
1009
1010 codec_config_->task_type_ = 913 codec_config_->task_type_ =
1011 g_avda_codec_allocator.Get().TaskTypeForAllocation(); 914 AVDACodecAllocator::Instance()->TaskTypeForAllocation();
1012 if (codec_config_->task_type_ == AVDACodecAllocator::TaskType::FAILED_CODEC) { 915 if (codec_config_->task_type_ == TaskType::FAILED_CODEC) {
1013 OnCodecConfigured(nullptr); 916 OnCodecConfigured(nullptr);
1014 return false; 917 return false;
1015 } 918 }
1016 919
1017 std::unique_ptr<VideoCodecBridge> media_codec = 920 std::unique_ptr<VideoCodecBridge> media_codec =
1018 ConfigureMediaCodecOnAnyThread(codec_config_); 921 AVDACodecAllocator::Instance()->CreateMediaCodecSync(codec_config_);
1019 OnCodecConfigured(std::move(media_codec)); 922 OnCodecConfigured(std::move(media_codec));
1020 return !!media_codec_; 923 return !!media_codec_;
1021 } 924 }
1022 925
1023 std::unique_ptr<VideoCodecBridge>
1024 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread(
1025 scoped_refptr<CodecConfig> codec_config) {
1026 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec");
1027
1028 jobject media_crypto = codec_config->media_crypto_
1029 ? codec_config->media_crypto_->obj()
1030 : nullptr;
1031
1032 // |needs_protected_surface_| implies encrypted stream.
1033 DCHECK(!codec_config->needs_protected_surface_ || media_crypto);
1034
1035 const bool require_software_codec =
1036 codec_config->task_type_ == AVDACodecAllocator::TaskType::SW_CODEC;
1037
1038 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder(
1039 codec_config->codec_, codec_config->needs_protected_surface_,
1040 codec_config->initial_expected_coded_size_,
1041 codec_config->surface_.j_surface().obj(), media_crypto,
1042 codec_config->csd0_, codec_config->csd1_, true, require_software_codec));
1043
1044 return codec;
1045 }
1046
1047 void AndroidVideoDecodeAccelerator::OnCodecConfigured( 926 void AndroidVideoDecodeAccelerator::OnCodecConfigured(
1048 std::unique_ptr<VideoCodecBridge> media_codec) { 927 std::unique_ptr<VideoCodecBridge> media_codec) {
1049 DCHECK(thread_checker_.CalledOnValidThread()); 928 DCHECK(thread_checker_.CalledOnValidThread());
1050 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); 929 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED);
1051 930
1052 // If we are supposed to notify that initialization is complete, then do so 931 // If we are supposed to notify that initialization is complete, then do so
1053 // now. Otherwise, this is a reconfiguration. 932 // now. Otherwise, this is a reconfiguration.
1054 if (deferred_initialization_pending_) { 933 if (deferred_initialization_pending_) {
1055 // Losing the output surface is not considered an error state, so notify 934 // Losing the output surface is not considered an error state, so notify
1056 // success. The client will destroy this soon. 935 // success. The client will destroy this soon.
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 StartCodecDrain(DRAIN_FOR_RESET); 1105 StartCodecDrain(DRAIN_FOR_RESET);
1227 } else { 1106 } else {
1228 ResetCodecState(); 1107 ResetCodecState();
1229 base::ThreadTaskRunnerHandle::Get()->PostTask( 1108 base::ThreadTaskRunnerHandle::Get()->PostTask(
1230 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone, 1109 FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone,
1231 weak_this_factory_.GetWeakPtr())); 1110 weak_this_factory_.GetWeakPtr()));
1232 } 1111 }
1233 } 1112 }
1234 1113
1235 void AndroidVideoDecodeAccelerator::SetSurface(int32_t surface_id) { 1114 void AndroidVideoDecodeAccelerator::SetSurface(int32_t surface_id) {
1115 DVLOG(1) << __func__;
1116 DCHECK(thread_checker_.CalledOnValidThread());
1117
1236 if (surface_id == config_.surface_id) { 1118 if (surface_id == config_.surface_id) {
1237 pending_surface_id_.reset(); 1119 pending_surface_id_.reset();
1238 return; 1120 return;
1239 } 1121 }
1240 1122
1241 // Surface changes never take effect immediately, they will be handled during 1123 // Surface changes never take effect immediately, they will be handled during
1242 // DequeOutput() once we get to a good switch point or immediately during an 1124 // DequeOutput() once we get to a good switch point or immediately during an
1243 // OnDestroyingSurface() call. 1125 // OnSurfaceDestroyed() call.
1244 pending_surface_id_ = surface_id; 1126 pending_surface_id_ = surface_id;
1245 } 1127 }
1246 1128
1247 void AndroidVideoDecodeAccelerator::Destroy() { 1129 void AndroidVideoDecodeAccelerator::Destroy() {
1248 DVLOG(1) << __FUNCTION__; 1130 DVLOG(1) << __FUNCTION__;
1249 DCHECK(thread_checker_.CalledOnValidThread()); 1131 DCHECK(thread_checker_.CalledOnValidThread());
1250 1132
1251 picture_buffer_manager_.Destroy(output_picture_buffers_); 1133 picture_buffer_manager_.Destroy(output_picture_buffers_);
1252 1134
1253 client_ = nullptr; 1135 client_ = nullptr;
1254 1136
1255 // Some VP8 files require a complete MediaCodec drain before we can call 1137 // Some VP8 files require a complete MediaCodec drain before we can call
1256 // MediaCodec.flush() or MediaCodec.release(). http://crbug.com/598963. In 1138 // MediaCodec.flush() or MediaCodec.release(). http://crbug.com/598963. In
1257 // that case, postpone ActualDestroy() until after the drain. 1139 // that case, postpone ActualDestroy() until after the drain.
1258 if (media_codec_ && codec_config_->codec_ == kCodecVP8) { 1140 if (media_codec_ && codec_config_->codec_ == kCodecVP8) {
1259 // Clear |pending_bitstream_records_|. 1141 // Clear |pending_bitstream_records_|.
1260 while (!pending_bitstream_records_.empty()) 1142 while (!pending_bitstream_records_.empty())
1261 pending_bitstream_records_.pop(); 1143 pending_bitstream_records_.pop();
1262 1144
1263 StartCodecDrain(DRAIN_FOR_DESTROY); 1145 StartCodecDrain(DRAIN_FOR_DESTROY);
1264 } else { 1146 } else {
1265 ActualDestroy(); 1147 ActualDestroy();
1266 } 1148 }
1267 } 1149 }
1268 1150
1269 void AndroidVideoDecodeAccelerator::ActualDestroy() { 1151 void AndroidVideoDecodeAccelerator::ActualDestroy() {
1270 DVLOG(1) << __FUNCTION__; 1152 DVLOG(1) << __FUNCTION__;
1271 DCHECK(thread_checker_.CalledOnValidThread()); 1153 DCHECK(thread_checker_.CalledOnValidThread());
1272 1154
1273 if (!on_destroying_surface_cb_.is_null()) {
1274 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback(
1275 on_destroying_surface_cb_);
1276 }
1277
1278 // We no longer care about |surface_id|, in case we did before. It's okay
1279 // if we have no surface and/or weren't the owner or a waiter.
1280 g_avda_manager.Get().DeallocateSurface(config_.surface_id, this);
1281
1282 // Note that async codec construction might still be in progress. In that 1155 // Note that async codec construction might still be in progress. In that
1283 // case, the codec will be deleted when it completes once we invalidate all 1156 // case, the codec will be deleted when it completes once we invalidate all
1284 // our weak refs. 1157 // our weak refs.
1285 weak_this_factory_.InvalidateWeakPtrs(); 1158 weak_this_factory_.InvalidateWeakPtrs();
1159 g_avda_manager.Get().StopTimer(this);
1286 if (media_codec_) { 1160 if (media_codec_) {
1287 g_avda_manager.Get().StopTimer(this); 1161 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1288 ReleaseMediaCodec(); 1162 std::move(media_codec_), codec_config_->task_type_, config_.surface_id);
1289 } 1163 }
1290 1164
1165 // We no longer care about |surface_id|, in case we did before. It's okay
1166 // if we have no surface and/or weren't the owner or a waiter.
1167 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id);
1168
1291 delete this; 1169 delete this;
1292 } 1170 }
1293 1171
1294 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( 1172 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
1295 const base::WeakPtr<Client>& decode_client, 1173 const base::WeakPtr<Client>& decode_client,
1296 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { 1174 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
1297 return false; 1175 return false;
1298 } 1176 }
1299 1177
1300 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const { 1178 const gfx::Size& AndroidVideoDecodeAccelerator::GetSize() const {
1301 return size_; 1179 return size_;
1302 } 1180 }
1303 1181
1304 base::WeakPtr<gpu::gles2::GLES2Decoder> 1182 base::WeakPtr<gpu::gles2::GLES2Decoder>
1305 AndroidVideoDecodeAccelerator::GetGlDecoder() const { 1183 AndroidVideoDecodeAccelerator::GetGlDecoder() const {
1306 return get_gles2_decoder_cb_.Run(); 1184 return get_gles2_decoder_cb_.Run();
1307 } 1185 }
1308 1186
1309 void AndroidVideoDecodeAccelerator::OnDestroyingSurface(int surface_id) { 1187 void AndroidVideoDecodeAccelerator::OnSurfaceDestroyed() {
1188 DVLOG(1) << __func__;
1189 TRACE_EVENT0("media", "AVDA::OnSurfaceDestroyed");
1310 DCHECK(thread_checker_.CalledOnValidThread()); 1190 DCHECK(thread_checker_.CalledOnValidThread());
1311 TRACE_EVENT0("media", "AVDA::OnDestroyingSurface");
1312 DVLOG(1) << __FUNCTION__ << " surface_id: " << surface_id;
1313
1314 if (surface_id != config_.surface_id)
1315 return;
1316 1191
1317 // If the API is available avoid having to restart the decoder in order to 1192 // If the API is available avoid having to restart the decoder in order to
1318 // leave fullscreen. If we don't clear the surface immediately during this 1193 // leave fullscreen. If we don't clear the surface immediately during this
1319 // callback, the MediaCodec will throw an error as the surface is destroyed. 1194 // callback, the MediaCodec will throw an error as the surface is destroyed.
1320 if (base::android::BuildInfo::GetInstance()->sdk_int() >= 23) { 1195 if (base::android::BuildInfo::GetInstance()->sdk_int() >= 23) {
1321 // Since we can't wait for a transition, we must invalidate all outstanding 1196 // Since we can't wait for a transition, we must invalidate all outstanding
1322 // picture buffers to avoid putting the GL system in a broken state. 1197 // picture buffers to avoid putting the GL system in a broken state.
1323 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_); 1198 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_);
1324 1199
1325 // Switch away from the surface being destroyed to a surface texture. 1200 // Switch away from the surface being destroyed to a surface texture.
1326 DCHECK_NE(config_.surface_id, SurfaceManager::kNoSurfaceID); 1201 DCHECK_NE(config_.surface_id, SurfaceManager::kNoSurfaceID);
1327 1202
1328 // The leaving fullscreen notification may come in before this point. 1203 // The leaving fullscreen notification may come in before this point.
1329 if (pending_surface_id_) 1204 if (pending_surface_id_)
1330 DCHECK_EQ(pending_surface_id_.value(), SurfaceManager::kNoSurfaceID); 1205 DCHECK_EQ(pending_surface_id_.value(), SurfaceManager::kNoSurfaceID);
1331 1206
1332 pending_surface_id_ = SurfaceManager::kNoSurfaceID; 1207 pending_surface_id_ = SurfaceManager::kNoSurfaceID;
1333 UpdateSurface(); 1208 UpdateSurface();
1334 return; 1209 return;
1335 } 1210 }
1336 1211
1337 // If we're currently asynchronously configuring a codec, it will be destroyed 1212 // If we're currently asynchronously configuring a codec, it will be destroyed
1338 // when configuration completes and it notices that |state_| has changed to 1213 // when configuration completes and it notices that |state_| has changed to
1339 // SURFACE_DESTROYED. 1214 // SURFACE_DESTROYED.
1340 state_ = SURFACE_DESTROYED; 1215 state_ = SURFACE_DESTROYED;
1341 if (media_codec_) { 1216 if (media_codec_) {
1342 ReleaseMediaCodec(); 1217 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1343 picture_buffer_manager_.CodecChanged(media_codec_.get()); 1218 std::move(media_codec_), codec_config_->task_type_, config_.surface_id);
1219 picture_buffer_manager_.CodecChanged(nullptr);
1344 } 1220 }
1221
1345 // If we're draining, signal completion now because the drain can no longer 1222 // If we're draining, signal completion now because the drain can no longer
1346 // proceed. 1223 // proceed.
1347 if (drain_type_ != DRAIN_TYPE_NONE) 1224 if (drain_type_ != DRAIN_TYPE_NONE)
1348 OnDrainCompleted(); 1225 OnDrainCompleted();
1349 } 1226 }
1350 1227
1351 void AndroidVideoDecodeAccelerator::InitializeCdm() { 1228 void AndroidVideoDecodeAccelerator::InitializeCdm() {
1352 DVLOG(2) << __FUNCTION__ << ": " << config_.cdm_id; 1229 DVLOG(2) << __FUNCTION__ << ": " << config_.cdm_id;
1353 1230
1354 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) 1231 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1465 } else { 1342 } else {
1466 most_recent_work_ = now; 1343 most_recent_work_ = now;
1467 } 1344 }
1468 1345
1469 if (should_be_running) 1346 if (should_be_running)
1470 g_avda_manager.Get().StartTimer(this); 1347 g_avda_manager.Get().StartTimer(this);
1471 else 1348 else
1472 g_avda_manager.Get().StopTimer(this); 1349 g_avda_manager.Get().StopTimer(this);
1473 } 1350 }
1474 1351
1475 void AndroidVideoDecodeAccelerator::ReleaseMediaCodec() {
1476 if (!media_codec_)
1477 return;
1478
1479 // Post it to the same thread as was used to allocate it, and it'll get freed
1480 // if that thread isn't hung waiting on mediaserver. We can't release it
1481 // on this thread since it might hang up.
1482 g_avda_codec_allocator.Get()
1483 .TaskRunnerFor(codec_config_->task_type_)
1484 ->DeleteSoon(FROM_HERE, media_codec_.release());
1485 }
1486
1487 // static 1352 // static
1488 VideoDecodeAccelerator::Capabilities 1353 VideoDecodeAccelerator::Capabilities
1489 AndroidVideoDecodeAccelerator::GetCapabilities( 1354 AndroidVideoDecodeAccelerator::GetCapabilities(
1490 const gpu::GpuPreferences& gpu_preferences) { 1355 const gpu::GpuPreferences& gpu_preferences) {
1491 Capabilities capabilities; 1356 Capabilities capabilities;
1492 SupportedProfiles& profiles = capabilities.supported_profiles; 1357 SupportedProfiles& profiles = capabilities.supported_profiles;
1493 1358
1494 if (MediaCodecUtil::IsVp8DecoderAvailable()) { 1359 if (MediaCodecUtil::IsVp8DecoderAvailable()) {
1495 SupportedProfile profile; 1360 SupportedProfile profile;
1496 profile.profile = VP8PROFILE_ANY; 1361 profile.profile = VP8PROFILE_ANY;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1586 const { 1451 const {
1587 // Prevent MediaCodec from using its internal software decoders when we have 1452 // Prevent MediaCodec from using its internal software decoders when we have
1588 // more secure and up to date versions in the renderer process. 1453 // more secure and up to date versions in the renderer process.
1589 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 || 1454 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 ||
1590 codec_config_->codec_ == kCodecVP9); 1455 codec_config_->codec_ == kCodecVP9);
1591 } 1456 }
1592 1457
1593 bool AndroidVideoDecodeAccelerator::UpdateSurface() { 1458 bool AndroidVideoDecodeAccelerator::UpdateSurface() {
1594 DCHECK(pending_surface_id_); 1459 DCHECK(pending_surface_id_);
1595 DCHECK_NE(config_.surface_id, pending_surface_id_.value()); 1460 DCHECK_NE(config_.surface_id, pending_surface_id_.value());
1461 DCHECK(config_.surface_id == SurfaceManager::kNoSurfaceID ||
1462 pending_surface_id_.value() == SurfaceManager::kNoSurfaceID);
1463
1464 const int previous_surface_id = config_.surface_id;
1465 const int new_surface_id = pending_surface_id_.value();
1466 pending_surface_id_.reset();
1467 bool success = true;
1468
1469 // TODO(watk): Fix this so we can wait for the new surface to be allocated.
1470 if (!AVDACodecAllocator::Instance()->AllocateSurface(this, new_surface_id)) {
1471 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to allocate the new surface");
1472 success = false;
1473 }
1596 1474
1597 // Ensure the current context is active when switching surfaces; we may need 1475 // Ensure the current context is active when switching surfaces; we may need
1598 // to create a new texture. 1476 // to create a new texture.
1599 if (!make_context_current_cb_.Run()) { 1477 if (success && !make_context_current_cb_.Run()) {
1600 NOTIFY_ERROR(PLATFORM_FAILURE, 1478 NOTIFY_ERROR(PLATFORM_FAILURE,
1601 "Failed to make this decoder's GL context current when " 1479 "Failed to make this decoder's GL context current when "
1602 "switching surfaces."); 1480 "switching surfaces.");
1603 return false; 1481 success = false;
1604 } 1482 }
1605 1483
1606 config_.surface_id = pending_surface_id_.value(); 1484 if (success) {
1607 codec_config_->surface_ = 1485 codec_config_->surface_ =
1608 picture_buffer_manager_.Initialize(pending_surface_id_.value()); 1486 picture_buffer_manager_.Initialize(new_surface_id);
1609 if (codec_config_->surface_.IsEmpty()) { 1487 if (codec_config_->surface_.IsEmpty()) {
1610 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces."); 1488 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces.");
1611 return false; 1489 success = false;
1490 }
1612 } 1491 }
1613 1492
1614 if (media_codec_ && 1493 if (success && media_codec_ &&
1615 !media_codec_->SetSurface(codec_config_->surface_.j_surface().obj())) { 1494 !media_codec_->SetSurface(codec_config_->surface_.j_surface().obj())) {
1616 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces."); 1495 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces.");
1617 return false; 1496 success = false;
1618 } 1497 }
1619 1498
1620 pending_surface_id_.reset(); 1499 if (success) {
1621 return true; 1500 config_.surface_id = new_surface_id;
1501 } else {
1502 // This might be called from OnSurfaceDestroyed(), so we have to release the
1503 // MediaCodec if we failed to switch the surface.
1504 if (media_codec_) {
1505 AVDACodecAllocator::Instance()->ReleaseMediaCodec(
1506 std::move(media_codec_), codec_config_->task_type_,
1507 previous_surface_id);
1508 picture_buffer_manager_.CodecChanged(nullptr);
1509 }
1510 AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id);
1511 }
1512
1513 // Regardless of whether we succeeded, we no longer own the previous surface.
1514 AVDACodecAllocator::Instance()->DeallocateSurface(this, previous_surface_id);
1515
1516 return success;
1622 } 1517 }
1623 1518
1624 } // namespace media 1519 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/android_video_decode_accelerator.h ('k') | media/gpu/avda_codec_allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698