Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 int pending_surface_id = pending_surface_id_.value(); | |
| 1465 pending_surface_id_.reset(); | |
| 1466 bool success = true; | |
| 1467 | |
| 1468 // TODO(watk): Fix this so we can wait for the new surface to be allocated. | |
| 1469 if (!AVDACodecAllocator::Instance()->AllocateSurface(this, | |
| 1470 pending_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(); | |
| 1607 codec_config_->surface_ = | 1484 codec_config_->surface_ = |
| 1608 picture_buffer_manager_.Initialize(pending_surface_id_.value()); | 1485 picture_buffer_manager_.Initialize(pending_surface_id); |
| 1609 if (codec_config_->surface_.IsEmpty()) { | 1486 if (success && codec_config_->surface_.IsEmpty()) { |
| 1610 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces."); | 1487 NOTIFY_ERROR(PLATFORM_FAILURE, "Failed to switch surfaces."); |
| 1611 return false; | 1488 success = false; |
| 1612 } | 1489 } |
| 1613 | 1490 |
| 1614 if (media_codec_ && | 1491 if (success && media_codec_ && |
| 1615 !media_codec_->SetSurface(codec_config_->surface_.j_surface().obj())) { | 1492 !media_codec_->SetSurface(codec_config_->surface_.j_surface().obj())) { |
| 1616 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces."); | 1493 NOTIFY_ERROR(PLATFORM_FAILURE, "MediaCodec failed to switch surfaces."); |
| 1617 return false; | 1494 success = false; |
| 1618 } | 1495 } |
| 1619 | 1496 |
| 1620 pending_surface_id_.reset(); | 1497 if (success) { |
| 1621 return true; | 1498 config_.surface_id = pending_surface_id; |
| 1499 } else { | |
| 1500 // This might be called from OnSurfaceDestroyed(), so we have to release the | |
| 1501 // MediaCodec if we failed to switch the surface. | |
| 1502 if (media_codec_) { | |
| 1503 AVDACodecAllocator::Instance()->ReleaseMediaCodec( | |
| 1504 std::move(media_codec_), codec_config_->task_type_, | |
| 1505 config_.surface_id); | |
| 1506 picture_buffer_manager_.CodecChanged(nullptr); | |
| 1507 } | |
| 1508 AVDACodecAllocator::Instance()->DeallocateSurface(this, pending_surface_id); | |
| 1509 } | |
| 1510 | |
| 1511 // Regardless of whether we succeeded, we no longer own the original surface. | |
| 1512 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id); | |
|
liberato (no reviews please)
2016/11/22 18:49:22
on success, isn't this now equal to |pending_surfa
watk
2016/11/22 20:21:38
Oh jeez, good catch! Wish I could unit test this :
| |
| 1513 | |
| 1514 return success; | |
| 1622 } | 1515 } |
| 1623 | 1516 |
| 1624 } // namespace media | 1517 } // namespace media |
| OLD | NEW |