| 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 ~AVDAManager() = delete; |
| 170 | |
| 171 AVDAManager() {} | |
| 172 ~AVDAManager() { NOTREACHED(); } | |
| 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 15 matching lines...) Expand all Loading... |
| 236 pending_input_buf_index_(-1), | 236 pending_input_buf_index_(-1), |
| 237 during_initialize_(false), | 237 during_initialize_(false), |
| 238 deferred_initialization_pending_(false), | 238 deferred_initialization_pending_(false), |
| 239 codec_needs_reset_(false), | 239 codec_needs_reset_(false), |
| 240 defer_surface_creation_(false), | 240 defer_surface_creation_(false), |
| 241 last_release_task_type_(TaskType::AUTO_CODEC), | 241 last_release_task_type_(TaskType::AUTO_CODEC), |
| 242 weak_this_factory_(this) {} | 242 weak_this_factory_(this) {} |
| 243 | 243 |
| 244 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 244 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| 245 DCHECK(thread_checker_.CalledOnValidThread()); | 245 DCHECK(thread_checker_.CalledOnValidThread()); |
| 246 g_avda_manager.Get().StopTimer(this); | 246 GetManager()->StopTimer(this); |
| 247 AVDACodecAllocator::Instance()->StopThread(this); | 247 AVDACodecAllocator::Instance()->StopThread(this); |
| 248 | 248 |
| 249 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 249 #if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
| 250 if (!media_drm_bridge_cdm_context_) | 250 if (!media_drm_bridge_cdm_context_) |
| 251 return; | 251 return; |
| 252 | 252 |
| 253 DCHECK(cdm_registration_id_); | 253 DCHECK(cdm_registration_id_); |
| 254 | 254 |
| 255 // Cancel previously registered callback (if any). | 255 // Cancel previously registered callback (if any). |
| 256 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB( | 256 media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB( |
| (...skipping 860 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1117 // Flush the codec if possible, or create a new one if not. | 1117 // Flush the codec if possible, or create a new one if not. |
| 1118 if (!did_codec_error_happen && | 1118 if (!did_codec_error_happen && |
| 1119 !MediaCodecUtil::CodecNeedsFlushWorkaround(media_codec_.get())) { | 1119 !MediaCodecUtil::CodecNeedsFlushWorkaround(media_codec_.get())) { |
| 1120 DVLOG(3) << __func__ << " Flushing MediaCodec."; | 1120 DVLOG(3) << __func__ << " Flushing MediaCodec."; |
| 1121 media_codec_->Flush(); | 1121 media_codec_->Flush(); |
| 1122 // Since we just flushed all the output buffers, make sure that nothing is | 1122 // Since we just flushed all the output buffers, make sure that nothing is |
| 1123 // using them. | 1123 // using them. |
| 1124 picture_buffer_manager_.CodecChanged(media_codec_.get()); | 1124 picture_buffer_manager_.CodecChanged(media_codec_.get()); |
| 1125 } else { | 1125 } else { |
| 1126 DVLOG(3) << __func__ << " Deleting the MediaCodec and creating a new one."; | 1126 DVLOG(3) << __func__ << " Deleting the MediaCodec and creating a new one."; |
| 1127 g_avda_manager.Get().StopTimer(this); | 1127 GetManager()->StopTimer(this); |
| 1128 ConfigureMediaCodecAsynchronously(); | 1128 ConfigureMediaCodecAsynchronously(); |
| 1129 } | 1129 } |
| 1130 } | 1130 } |
| 1131 | 1131 |
| 1132 void AndroidVideoDecodeAccelerator::Reset() { | 1132 void AndroidVideoDecodeAccelerator::Reset() { |
| 1133 DVLOG(1) << __func__; | 1133 DVLOG(1) << __func__; |
| 1134 DCHECK(thread_checker_.CalledOnValidThread()); | 1134 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1135 TRACE_EVENT0("media", "AVDA::Reset"); | 1135 TRACE_EVENT0("media", "AVDA::Reset"); |
| 1136 | 1136 |
| 1137 if (defer_surface_creation_) { | 1137 if (defer_surface_creation_) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 } | 1191 } |
| 1192 | 1192 |
| 1193 void AndroidVideoDecodeAccelerator::ActualDestroy() { | 1193 void AndroidVideoDecodeAccelerator::ActualDestroy() { |
| 1194 DVLOG(1) << __func__; | 1194 DVLOG(1) << __func__; |
| 1195 DCHECK(thread_checker_.CalledOnValidThread()); | 1195 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1196 | 1196 |
| 1197 // Note that async codec construction might still be in progress. In that | 1197 // Note that async codec construction might still be in progress. In that |
| 1198 // case, the codec will be deleted when it completes once we invalidate all | 1198 // case, the codec will be deleted when it completes once we invalidate all |
| 1199 // our weak refs. | 1199 // our weak refs. |
| 1200 weak_this_factory_.InvalidateWeakPtrs(); | 1200 weak_this_factory_.InvalidateWeakPtrs(); |
| 1201 g_avda_manager.Get().StopTimer(this); | 1201 GetManager()->StopTimer(this); |
| 1202 ReleaseCodec(); | 1202 ReleaseCodec(); |
| 1203 | 1203 |
| 1204 // We no longer care about |surface_id|, in case we did before. It's okay | 1204 // We no longer care about |surface_id|, in case we did before. It's okay |
| 1205 // if we have no surface and/or weren't the owner or a waiter. | 1205 // if we have no surface and/or weren't the owner or a waiter. |
| 1206 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id); | 1206 AVDACodecAllocator::Instance()->DeallocateSurface(this, config_.surface_id); |
| 1207 | 1207 |
| 1208 // Hop the SurfaceTexture release call through the task runner used last time | 1208 // Hop the SurfaceTexture release call through the task runner used last time |
| 1209 // we released a codec. This ensures that we release the surface texture after | 1209 // we released a codec. This ensures that we release the surface texture after |
| 1210 // the codec it's attached to (if any) is released. It's not sufficient to use | 1210 // the codec it's attached to (if any) is released. It's not sufficient to use |
| 1211 // |codec_config_->task_type| because that might have changed since we | 1211 // |codec_config_->task_type| because that might have changed since we |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1414 // Make sure that we have done work recently enough, else stop the timer. | 1414 // Make sure that we have done work recently enough, else stop the timer. |
| 1415 if (now - most_recent_work_ > IdleTimerTimeOut) { | 1415 if (now - most_recent_work_ > IdleTimerTimeOut) { |
| 1416 most_recent_work_ = base::TimeTicks(); | 1416 most_recent_work_ = base::TimeTicks(); |
| 1417 should_be_running = false; | 1417 should_be_running = false; |
| 1418 } | 1418 } |
| 1419 } else { | 1419 } else { |
| 1420 most_recent_work_ = now; | 1420 most_recent_work_ = now; |
| 1421 } | 1421 } |
| 1422 | 1422 |
| 1423 if (should_be_running) | 1423 if (should_be_running) |
| 1424 g_avda_manager.Get().StartTimer(this); | 1424 GetManager()->StartTimer(this); |
| 1425 else | 1425 else |
| 1426 g_avda_manager.Get().StopTimer(this); | 1426 GetManager()->StopTimer(this); |
| 1427 } | 1427 } |
| 1428 | 1428 |
| 1429 // static | 1429 // static |
| 1430 VideoDecodeAccelerator::Capabilities | 1430 VideoDecodeAccelerator::Capabilities |
| 1431 AndroidVideoDecodeAccelerator::GetCapabilities( | 1431 AndroidVideoDecodeAccelerator::GetCapabilities( |
| 1432 const gpu::GpuPreferences& gpu_preferences) { | 1432 const gpu::GpuPreferences& gpu_preferences) { |
| 1433 Capabilities capabilities; | 1433 Capabilities capabilities; |
| 1434 SupportedProfiles& profiles = capabilities.supported_profiles; | 1434 SupportedProfiles& profiles = capabilities.supported_profiles; |
| 1435 | 1435 |
| 1436 if (MediaCodecUtil::IsVp8DecoderAvailable()) { | 1436 if (MediaCodecUtil::IsVp8DecoderAvailable()) { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1593 if (!media_codec_) | 1593 if (!media_codec_) |
| 1594 return; | 1594 return; |
| 1595 | 1595 |
| 1596 picture_buffer_manager_.CodecChanged(nullptr); | 1596 picture_buffer_manager_.CodecChanged(nullptr); |
| 1597 AVDACodecAllocator::Instance()->ReleaseMediaCodec( | 1597 AVDACodecAllocator::Instance()->ReleaseMediaCodec( |
| 1598 std::move(media_codec_), codec_config_->task_type, config_.surface_id); | 1598 std::move(media_codec_), codec_config_->task_type, config_.surface_id); |
| 1599 last_release_task_type_ = codec_config_->task_type; | 1599 last_release_task_type_ = codec_config_->task_type; |
| 1600 } | 1600 } |
| 1601 | 1601 |
| 1602 } // namespace media | 1602 } // namespace media |
| OLD | NEW |