| 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 "content/common/gpu/media/android_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/message_loop/message_loop.h" | 16 #include "base/message_loop/message_loop.h" |
| 17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 18 #include "base/task_runner_util.h" | 18 #include "base/task_runner_util.h" |
| 19 #include "base/threading/thread_checker.h" |
| 19 #include "base/trace_event/trace_event.h" | 20 #include "base/trace_event/trace_event.h" |
| 20 #include "content/common/gpu/media/android_copying_backing_strategy.h" | 21 #include "content/common/gpu/media/android_copying_backing_strategy.h" |
| 21 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" | 22 #include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h
" |
| 22 #include "content/common/gpu/media/avda_return_on_failure.h" | 23 #include "content/common/gpu/media/avda_return_on_failure.h" |
| 23 #include "content/common/gpu/media/shared_memory_region.h" | 24 #include "content/common/gpu/media/shared_memory_region.h" |
| 24 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 25 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| 25 #include "gpu/command_buffer/service/mailbox_manager.h" | 26 #include "gpu/command_buffer/service/mailbox_manager.h" |
| 26 #include "gpu/ipc/service/gpu_channel.h" | 27 #include "gpu/ipc/service/gpu_channel.h" |
| 27 #include "media/base/android/media_codec_bridge.h" | 28 #include "media/base/android/media_codec_bridge.h" |
| 28 #include "media/base/android/media_codec_util.h" | 29 #include "media/base/android/media_codec_util.h" |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 // behind this is that, if we're waiting for long enough, then either (a) | 173 // behind this is that, if we're waiting for long enough, then either (a) |
| 173 // MediaCodec is broken or (b) MediaCodec is waiting on us to change state | 174 // MediaCodec is broken or (b) MediaCodec is waiting on us to change state |
| 174 // (e.g., get new demuxed data / get a free picture buffer / return an output | 175 // (e.g., get new demuxed data / get a free picture buffer / return an output |
| 175 // buffer to MediaCodec). This is inherently a race, since we don't know if | 176 // buffer to MediaCodec). This is inherently a race, since we don't know if |
| 176 // MediaCodec is broken or just slow. Since the MediaCodec API doesn't let | 177 // MediaCodec is broken or just slow. Since the MediaCodec API doesn't let |
| 177 // us wait on MediaCodec state changes prior to L, we more or less have to | 178 // us wait on MediaCodec state changes prior to L, we more or less have to |
| 178 // time out or keep polling forever in some common cases. | 179 // time out or keep polling forever in some common cases. |
| 179 class AVDATimerManager { | 180 class AVDATimerManager { |
| 180 public: | 181 public: |
| 181 // Make sure that the construction thread is started for |avda_instance|. | 182 // Make sure that the construction thread is started for |avda_instance|. |
| 182 void StartThread(AndroidVideoDecodeAccelerator* avda_instance) { | 183 bool StartThread(AndroidVideoDecodeAccelerator* avda_instance) { |
| 183 if (thread_avda_instances_.empty()) | 184 DCHECK(thread_checker_.CalledOnValidThread()); |
| 184 construction_thread_.Start(); | 185 |
| 186 if (thread_avda_instances_.empty()) { |
| 187 if (!construction_thread_.Start()) { |
| 188 LOG(ERROR) << "Failed to start construction thread."; |
| 189 return false; |
| 190 } |
| 191 } |
| 185 | 192 |
| 186 thread_avda_instances_.insert(avda_instance); | 193 thread_avda_instances_.insert(avda_instance); |
| 194 return true; |
| 187 } | 195 } |
| 188 | 196 |
| 189 // |avda_instance| will no longer need the construction thread. Stop the | 197 // |avda_instance| will no longer need the construction thread. Stop the |
| 190 // thread if this is the last instance. | 198 // thread if this is the last instance. |
| 191 void StopThread(AndroidVideoDecodeAccelerator* avda_instance) { | 199 void StopThread(AndroidVideoDecodeAccelerator* avda_instance) { |
| 200 DCHECK(thread_checker_.CalledOnValidThread()); |
| 201 |
| 192 thread_avda_instances_.erase(avda_instance); | 202 thread_avda_instances_.erase(avda_instance); |
| 193 if (thread_avda_instances_.empty()) | 203 if (thread_avda_instances_.empty()) |
| 194 construction_thread_.Stop(); | 204 construction_thread_.Stop(); |
| 195 } | 205 } |
| 196 | 206 |
| 197 // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if | 207 // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if |
| 198 // the instance is already registered and the timer started. The first request | 208 // the instance is already registered and the timer started. The first request |
| 199 // will start the repeating timer on an interval of DecodePollDelay(). | 209 // will start the repeating timer on an interval of DecodePollDelay(). |
| 200 void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) { | 210 void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) { |
| 211 DCHECK(thread_checker_.CalledOnValidThread()); |
| 212 |
| 201 timer_avda_instances_.insert(avda_instance); | 213 timer_avda_instances_.insert(avda_instance); |
| 202 | 214 |
| 203 // If the timer is running, StopTimer() might have been called earlier, if | 215 // If the timer is running, StopTimer() might have been called earlier, if |
| 204 // so remove the instance from the pending erasures. | 216 // so remove the instance from the pending erasures. |
| 205 if (timer_running_) | 217 if (timer_running_) |
| 206 pending_erase_.erase(avda_instance); | 218 pending_erase_.erase(avda_instance); |
| 207 | 219 |
| 208 if (io_timer_.IsRunning()) | 220 if (io_timer_.IsRunning()) |
| 209 return; | 221 return; |
| 210 io_timer_.Start(FROM_HERE, DecodePollDelay(), this, | 222 io_timer_.Start(FROM_HERE, DecodePollDelay(), this, |
| 211 &AVDATimerManager::RunTimer); | 223 &AVDATimerManager::RunTimer); |
| 212 } | 224 } |
| 213 | 225 |
| 214 // Stop callbacks to |avda_instance|->DoIOTask(). Does nothing if the instance | 226 // Stop callbacks to |avda_instance|->DoIOTask(). Does nothing if the instance |
| 215 // is not registered. If there are no instances left, the repeating timer will | 227 // is not registered. If there are no instances left, the repeating timer will |
| 216 // be stopped. | 228 // be stopped. |
| 217 void StopTimer(AndroidVideoDecodeAccelerator* avda_instance) { | 229 void StopTimer(AndroidVideoDecodeAccelerator* avda_instance) { |
| 230 DCHECK(thread_checker_.CalledOnValidThread()); |
| 231 |
| 218 // If the timer is running, defer erasures to avoid iterator invalidation. | 232 // If the timer is running, defer erasures to avoid iterator invalidation. |
| 219 if (timer_running_) { | 233 if (timer_running_) { |
| 220 pending_erase_.insert(avda_instance); | 234 pending_erase_.insert(avda_instance); |
| 221 return; | 235 return; |
| 222 } | 236 } |
| 223 | 237 |
| 224 timer_avda_instances_.erase(avda_instance); | 238 timer_avda_instances_.erase(avda_instance); |
| 225 if (timer_avda_instances_.empty()) | 239 if (timer_avda_instances_.empty()) |
| 226 io_timer_.Stop(); | 240 io_timer_.Stop(); |
| 227 } | 241 } |
| 228 | 242 |
| 229 // Eventually, we should run the timer on this thread. For now, we just keep | 243 // Eventually, we should run the timer on this thread. For now, we just keep |
| 230 // it as a convenience for construction. | 244 // it as a convenience for construction. |
| 231 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { | 245 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { |
| 246 DCHECK(thread_checker_.CalledOnValidThread()); |
| 232 return construction_thread_.task_runner(); | 247 return construction_thread_.task_runner(); |
| 233 } | 248 } |
| 234 | 249 |
| 235 private: | 250 private: |
| 236 friend struct base::DefaultLazyInstanceTraits<AVDATimerManager>; | 251 friend struct base::DefaultLazyInstanceTraits<AVDATimerManager>; |
| 237 | 252 |
| 238 AVDATimerManager() : construction_thread_("AVDAThread") {} | 253 AVDATimerManager() : construction_thread_("AVDAThread") {} |
| 239 ~AVDATimerManager() { NOTREACHED(); } | 254 ~AVDATimerManager() { NOTREACHED(); } |
| 240 | 255 |
| 241 void RunTimer() { | 256 void RunTimer() { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 266 // Since we can't delete while iterating when using a set, defer erasure until | 281 // Since we can't delete while iterating when using a set, defer erasure until |
| 267 // after iteration complete. | 282 // after iteration complete. |
| 268 bool timer_running_ = false; | 283 bool timer_running_ = false; |
| 269 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; | 284 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; |
| 270 | 285 |
| 271 // Repeating timer responsible for draining pending IO to the codecs. | 286 // Repeating timer responsible for draining pending IO to the codecs. |
| 272 base::RepeatingTimer io_timer_; | 287 base::RepeatingTimer io_timer_; |
| 273 | 288 |
| 274 base::Thread construction_thread_; | 289 base::Thread construction_thread_; |
| 275 | 290 |
| 291 base::ThreadChecker thread_checker_; |
| 292 |
| 276 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); | 293 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); |
| 277 }; | 294 }; |
| 278 | 295 |
| 279 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = | 296 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = |
| 280 LAZY_INSTANCE_INITIALIZER; | 297 LAZY_INSTANCE_INITIALIZER; |
| 281 | 298 |
| 282 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {} | 299 AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {} |
| 283 | 300 |
| 284 AndroidVideoDecodeAccelerator::CodecConfig::~CodecConfig() {} | 301 AndroidVideoDecodeAccelerator::CodecConfig::~CodecConfig() {} |
| 285 | 302 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 // TODO(watk,liberato): move this into the strategy. | 417 // TODO(watk,liberato): move this into the strategy. |
| 401 scoped_refptr<gfx::SurfaceTexture> surface_texture = | 418 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
| 402 strategy_->GetSurfaceTexture(); | 419 strategy_->GetSurfaceTexture(); |
| 403 if (surface_texture) { | 420 if (surface_texture) { |
| 404 on_frame_available_handler_ = | 421 on_frame_available_handler_ = |
| 405 new OnFrameAvailableHandler(this, surface_texture); | 422 new OnFrameAvailableHandler(this, surface_texture); |
| 406 } | 423 } |
| 407 | 424 |
| 408 // Start the thread for async configuration, even if we don't need it now. | 425 // Start the thread for async configuration, even if we don't need it now. |
| 409 // ResetCodecState might rebuild the codec later, for example. | 426 // ResetCodecState might rebuild the codec later, for example. |
| 410 g_avda_timer.Pointer()->StartThread(this); | 427 if (!g_avda_timer.Pointer()->StartThread(this)) { |
| 428 LOG(ERROR) << "Failed to start thread for AVDA timer"; |
| 429 return false; |
| 430 } |
| 411 | 431 |
| 412 // If we are encrypted, then we aren't able to create the codec yet. | 432 // If we are encrypted, then we aren't able to create the codec yet. |
| 413 if (is_encrypted_) | 433 if (is_encrypted_) |
| 414 return true; | 434 return true; |
| 415 | 435 |
| 416 if (deferred_initialization_pending_) { | 436 if (deferred_initialization_pending_) { |
| 417 ConfigureMediaCodecAsynchronously(); | 437 ConfigureMediaCodecAsynchronously(); |
| 418 return true; | 438 return true; |
| 419 } | 439 } |
| 420 | 440 |
| (...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { | 1343 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { |
| 1324 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: | 1344 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: |
| 1325 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1345 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1326 } | 1346 } |
| 1327 } | 1347 } |
| 1328 | 1348 |
| 1329 return capabilities; | 1349 return capabilities; |
| 1330 } | 1350 } |
| 1331 | 1351 |
| 1332 } // namespace content | 1352 } // namespace content |
| OLD | NEW |