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 |
| 11 #include "base/android/build_info.h" | 11 #include "base/android/build_info.h" |
| 12 #include "base/auto_reset.h" | 12 #include "base/auto_reset.h" |
| 13 #include "base/bind.h" | 13 #include "base/bind.h" |
| 14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
| 15 #include "base/callback_helpers.h" | 15 #include "base/callback_helpers.h" |
| 16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 17 #include "base/lazy_instance.h" | |
| 18 #include "base/logging.h" | 17 #include "base/logging.h" |
| 19 #include "base/message_loop/message_loop.h" | 18 #include "base/message_loop/message_loop.h" |
| 20 #include "base/metrics/histogram_macros.h" | 19 #include "base/metrics/histogram_macros.h" |
| 21 #include "base/sys_info.h" | 20 #include "base/sys_info.h" |
| 22 #include "base/task_runner_util.h" | 21 #include "base/task_runner_util.h" |
| 23 #include "base/threading/thread.h" | 22 #include "base/threading/thread.h" |
| 24 #include "base/threading/thread_checker.h" | 23 #include "base/threading/thread_checker.h" |
| 25 #include "base/threading/thread_task_runner_handle.h" | 24 #include "base/threading/thread_task_runner_handle.h" |
| 26 #include "base/trace_event/trace_event.h" | 25 #include "base/trace_event/trace_event.h" |
| 27 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 26 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 123 // - Starting and stopping a shared "construction" thread for instantiating and | 122 // - Starting and stopping a shared "construction" thread for instantiating and |
| 124 // releasing MediaCodecs. | 123 // releasing MediaCodecs. |
| 125 // - Detecting when a task has hung on the construction thread so AVDAs can | 124 // - Detecting when a task has hung on the construction thread so AVDAs can |
| 126 // stop using it. | 125 // stop using it. |
| 127 // - Running a RepeatingTimer so that AVDAs can get a regular callback to | 126 // - Running a RepeatingTimer so that AVDAs can get a regular callback to |
| 128 // DoIOTask(). | 127 // DoIOTask(). |
| 129 // - Tracking the allocation of surfaces to AVDAs and delivering callbacks when | 128 // - Tracking the allocation of surfaces to AVDAs and delivering callbacks when |
| 130 // surfaces are released. | 129 // surfaces are released. |
| 131 class AVDAManager { | 130 class AVDAManager { |
| 132 public: | 131 public: |
| 132 AVDAManager() {} | |
| 133 | |
| 133 // Request periodic callback of |avda|->DoIOTask(). Does nothing if the | 134 // Request periodic callback of |avda|->DoIOTask(). Does nothing if the |
| 134 // instance is already registered and the timer started. The first request | 135 // instance is already registered and the timer started. The first request |
| 135 // will start the repeating timer on an interval of DecodePollDelay. | 136 // will start the repeating timer on an interval of DecodePollDelay. |
| 136 void StartTimer(AndroidVideoDecodeAccelerator* avda) { | 137 void StartTimer(AndroidVideoDecodeAccelerator* avda) { |
| 137 DCHECK(thread_checker_.CalledOnValidThread()); | 138 DCHECK(thread_checker_.CalledOnValidThread()); |
| 138 | 139 |
| 139 timer_avda_instances_.insert(avda); | 140 timer_avda_instances_.insert(avda); |
| 140 | 141 |
| 141 // If the timer is running, StopTimer() might have been called earlier, if | 142 // If the timer is running, StopTimer() might have been called earlier, if |
| 142 // so remove the instance from the pending erasures. | 143 // so remove the instance from the pending erasures. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 159 pending_erase_.insert(avda); | 160 pending_erase_.insert(avda); |
| 160 return; | 161 return; |
| 161 } | 162 } |
| 162 | 163 |
| 163 timer_avda_instances_.erase(avda); | 164 timer_avda_instances_.erase(avda); |
| 164 if (timer_avda_instances_.empty()) | 165 if (timer_avda_instances_.empty()) |
| 165 io_timer_.Stop(); | 166 io_timer_.Stop(); |
| 166 } | 167 } |
| 167 | 168 |
| 168 private: | 169 private: |
| 169 friend struct base::DefaultLazyInstanceTraits<AVDAManager>; | |
| 170 | |
| 171 AVDAManager() {} | |
| 172 ~AVDAManager() { NOTREACHED(); } | 170 ~AVDAManager() { NOTREACHED(); } |
|
Mark Mentovai
2017/01/31 21:33:56
You can switch this to the “= delete” form too.
DaleCurtis
2017/01/31 22:04:33
Done.
| |
| 173 | 171 |
| 174 void RunTimer() { | 172 void RunTimer() { |
| 175 { | 173 { |
| 176 // Call out to all AVDA instances, some of which may attempt to remove | 174 // Call out to all AVDA instances, some of which may attempt to remove |
| 177 // themselves from the list during this operation; those removals will be | 175 // themselves from the list during this operation; those removals will be |
| 178 // deferred until after all iterations are complete. | 176 // deferred until after all iterations are complete. |
| 179 base::AutoReset<bool> scoper(&timer_running_, true); | 177 base::AutoReset<bool> scoper(&timer_running_, true); |
| 180 for (auto* avda : timer_avda_instances_) | 178 for (auto* avda : timer_avda_instances_) |
| 181 avda->DoIOTask(false); | 179 avda->DoIOTask(false); |
| 182 } | 180 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 199 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; | 197 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; |
| 200 | 198 |
| 201 // Repeating timer responsible for draining pending IO to the codecs. | 199 // Repeating timer responsible for draining pending IO to the codecs. |
| 202 base::RepeatingTimer io_timer_; | 200 base::RepeatingTimer io_timer_; |
| 203 | 201 |
| 204 base::ThreadChecker thread_checker_; | 202 base::ThreadChecker thread_checker_; |
| 205 | 203 |
| 206 DISALLOW_COPY_AND_ASSIGN(AVDAManager); | 204 DISALLOW_COPY_AND_ASSIGN(AVDAManager); |
| 207 }; | 205 }; |
| 208 | 206 |
| 209 static base::LazyInstance<AVDAManager>::Leaky g_avda_manager = | 207 static AVDAManager* GetManager() { |
| 210 LAZY_INSTANCE_INITIALIZER; | 208 static AVDAManager* manager = new AVDAManager(); |
| 209 return manager; | |
| 210 } | |
| 211 | 211 |
| 212 AndroidVideoDecodeAccelerator::BitstreamRecord::BitstreamRecord( | 212 AndroidVideoDecodeAccelerator::BitstreamRecord::BitstreamRecord( |
| 213 const BitstreamBuffer& bitstream_buffer) | 213 const BitstreamBuffer& bitstream_buffer) |
| 214 : buffer(bitstream_buffer) { | 214 : buffer(bitstream_buffer) { |
| 215 if (buffer.id() != -1) | 215 if (buffer.id() != -1) |
| 216 memory.reset(new SharedMemoryRegion(buffer, true)); | 216 memory.reset(new SharedMemoryRegion(buffer, true)); |
| 217 } | 217 } |
| 218 | 218 |
| 219 AndroidVideoDecodeAccelerator::BitstreamRecord::BitstreamRecord( | 219 AndroidVideoDecodeAccelerator::BitstreamRecord::BitstreamRecord( |
| 220 BitstreamRecord&& other) | 220 BitstreamRecord&& other) |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 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 last_release_task_type_(TaskType::AUTO_CODEC), |
| 241 weak_this_factory_(this) {} | 241 weak_this_factory_(this) {} |
| 242 | 242 |
| 243 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 243 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| 244 DCHECK(thread_checker_.CalledOnValidThread()); | 244 DCHECK(thread_checker_.CalledOnValidThread()); |
| 245 g_avda_manager.Get().StopTimer(this); | 245 GetManager()->StopTimer(this); |
| 246 AVDACodecAllocator::Instance()->StopThread(this); | 246 AVDACodecAllocator::Instance()->StopThread(this); |
| 247 | 247 |
| 248 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 248 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 249 if (!media_drm_bridge_cdm_context_) | 249 if (!media_drm_bridge_cdm_context_) |
| 250 return; | 250 return; |
| 251 | 251 |
| 252 DCHECK(cdm_registration_id_); | 252 DCHECK(cdm_registration_id_); |
| 253 | 253 |
| 254 // Cancel previously registered callback (if any). | 254 // Cancel previously registered callback (if any). |
| 255 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB( | 255 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB( |
| (...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1058 // Flush the codec if possible, or create a new one if not. | 1058 // Flush the codec if possible, or create a new one if not. |
| 1059 if (!did_codec_error_happen && | 1059 if (!did_codec_error_happen && |
| 1060 !MediaCodecUtil::CodecNeedsFlushWorkaround(media_codec_.get())) { | 1060 !MediaCodecUtil::CodecNeedsFlushWorkaround(media_codec_.get())) { |
| 1061 DVLOG(3) << __func__ << " Flushing MediaCodec."; | 1061 DVLOG(3) << __func__ << " Flushing MediaCodec."; |
| 1062 media_codec_->Flush(); | 1062 media_codec_->Flush(); |
| 1063 // Since we just flushed all the output buffers, make sure that nothing is | 1063 // Since we just flushed all the output buffers, make sure that nothing is |
| 1064 // using them. | 1064 // using them. |
| 1065 picture_buffer_manager_.CodecChanged(media_codec_.get()); | 1065 picture_buffer_manager_.CodecChanged(media_codec_.get()); |
| 1066 } else { | 1066 } else { |
| 1067 DVLOG(3) << __func__ << " Deleting the MediaCodec and creating a new one."; | 1067 DVLOG(3) << __func__ << " Deleting the MediaCodec and creating a new one."; |
| 1068 g_avda_manager.Get().StopTimer(this); | 1068 GetManager()->StopTimer(this); |
| 1069 ConfigureMediaCodecAsynchronously(); | 1069 ConfigureMediaCodecAsynchronously(); |
| 1070 } | 1070 } |
| 1071 } | 1071 } |
| 1072 | 1072 |
| 1073 void AndroidVideoDecodeAccelerator::Reset() { | 1073 void AndroidVideoDecodeAccelerator::Reset() { |
| 1074 DVLOG(1) << __func__; | 1074 DVLOG(1) << __func__; |
| 1075 DCHECK(thread_checker_.CalledOnValidThread()); | 1075 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1076 TRACE_EVENT0("media", "AVDA::Reset"); | 1076 TRACE_EVENT0("media", "AVDA::Reset"); |
| 1077 | 1077 |
| 1078 if (defer_surface_creation_) { | 1078 if (defer_surface_creation_) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1132 } | 1132 } |
| 1133 | 1133 |
| 1134 void AndroidVideoDecodeAccelerator::ActualDestroy() { | 1134 void AndroidVideoDecodeAccelerator::ActualDestroy() { |
| 1135 DVLOG(1) << __func__; | 1135 DVLOG(1) << __func__; |
| 1136 DCHECK(thread_checker_.CalledOnValidThread()); | 1136 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1137 | 1137 |
| 1138 // 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 |
| 1139 // 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 |
| 1140 // our weak refs. | 1140 // our weak refs. |
| 1141 weak_this_factory_.InvalidateWeakPtrs(); | 1141 weak_this_factory_.InvalidateWeakPtrs(); |
| 1142 g_avda_manager.Get().StopTimer(this); | 1142 GetManager()->StopTimer(this); |
| 1143 ReleaseCodec(); | 1143 ReleaseCodec(); |
| 1144 | 1144 |
| 1145 // 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 |
| 1146 // 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. |
| 1147 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id); | 1147 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id); |
| 1148 | 1148 |
| 1149 // Hop the SurfaceTexture release call through the task runner used last time | 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 | 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 | 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 | 1152 // |codec_config_->task_type| because that might have changed since we |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1327 // Make sure that we have done work recently enough, else stop the timer. | 1327 // Make sure that we have done work recently enough, else stop the timer. |
| 1328 if (now - most_recent_work_ > IdleTimerTimeOut) { | 1328 if (now - most_recent_work_ > IdleTimerTimeOut) { |
| 1329 most_recent_work_ = base::TimeTicks(); | 1329 most_recent_work_ = base::TimeTicks(); |
| 1330 should_be_running = false; | 1330 should_be_running = false; |
| 1331 } | 1331 } |
| 1332 } else { | 1332 } else { |
| 1333 most_recent_work_ = now; | 1333 most_recent_work_ = now; |
| 1334 } | 1334 } |
| 1335 | 1335 |
| 1336 if (should_be_running) | 1336 if (should_be_running) |
| 1337 g_avda_manager.Get().StartTimer(this); | 1337 GetManager()->StartTimer(this); |
| 1338 else | 1338 else |
| 1339 g_avda_manager.Get().StopTimer(this); | 1339 GetManager()->StopTimer(this); |
| 1340 } | 1340 } |
| 1341 | 1341 |
| 1342 // static | 1342 // static |
| 1343 VideoDecodeAccelerator::Capabilities | 1343 VideoDecodeAccelerator::Capabilities |
| 1344 AndroidVideoDecodeAccelerator::GetCapabilities( | 1344 AndroidVideoDecodeAccelerator::GetCapabilities( |
| 1345 const gpu::GpuPreferences& gpu_preferences) { | 1345 const gpu::GpuPreferences& gpu_preferences) { |
| 1346 Capabilities capabilities; | 1346 Capabilities capabilities; |
| 1347 SupportedProfiles& profiles = capabilities.supported_profiles; | 1347 SupportedProfiles& profiles = capabilities.supported_profiles; |
| 1348 | 1348 |
| 1349 if (MediaCodecUtil::IsVp8DecoderAvailable()) { | 1349 if (MediaCodecUtil::IsVp8DecoderAvailable()) { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1507 if (!media_codec_) | 1507 if (!media_codec_) |
| 1508 return; | 1508 return; |
| 1509 | 1509 |
| 1510 picture_buffer_manager_.CodecChanged(nullptr); | 1510 picture_buffer_manager_.CodecChanged(nullptr); |
| 1511 AVDACodecAllocator::Instance()->ReleaseMediaCodec( | 1511 AVDACodecAllocator::Instance()->ReleaseMediaCodec( |
| 1512 std::move(media_codec_), codec_config_->task_type, config_.surface_id); | 1512 std::move(media_codec_), codec_config_->task_type, config_.surface_id); |
| 1513 last_release_task_type_ = codec_config_->task_type; | 1513 last_release_task_type_ = codec_config_->task_type; |
| 1514 } | 1514 } |
| 1515 | 1515 |
| 1516 } // namespace media | 1516 } // namespace media |
| OLD | NEW |