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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 H264PROFILE_SCALABLEHIGH, | 75 H264PROFILE_SCALABLEHIGH, |
76 H264PROFILE_STEREOHIGH, | 76 H264PROFILE_STEREOHIGH, |
77 H264PROFILE_MULTIVIEWHIGH}; | 77 H264PROFILE_MULTIVIEWHIGH}; |
78 | 78 |
79 // Because MediaCodec is thread-hostile (must be poked on a single thread) and | 79 // Because MediaCodec is thread-hostile (must be poked on a single thread) and |
80 // has no callback mechanism (b/11990118), we must drive it by polling for | 80 // has no callback mechanism (b/11990118), we must drive it by polling for |
81 // complete frames (and available input buffers, when the codec is fully | 81 // complete frames (and available input buffers, when the codec is fully |
82 // saturated). This function defines the polling delay. The value used is an | 82 // saturated). This function defines the polling delay. The value used is an |
83 // arbitrary choice that trades off CPU utilization (spinning) against latency. | 83 // arbitrary choice that trades off CPU utilization (spinning) against latency. |
84 // Mirrors android_video_encode_accelerator.cc:EncodePollDelay(). | 84 // Mirrors android_video_encode_accelerator.cc:EncodePollDelay(). |
85 static inline const base::TimeDelta DecodePollDelay() { | 85 // |
86 // An alternative to this polling scheme could be to dedicate a new thread | 86 // An alternative to this polling scheme could be to dedicate a new thread |
87 // (instead of using the ChildThread) to run the MediaCodec, and make that | 87 // (instead of using the ChildThread) to run the MediaCodec, and make that |
88 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it | 88 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it |
89 // believes the codec should complete "soon" (e.g. waiting for an input | 89 // believes the codec should complete "soon" (e.g. waiting for an input |
90 // buffer, or waiting for a picture when it knows enough complete input | 90 // buffer, or waiting for a picture when it knows enough complete input |
91 // pictures have been fed to saturate any internal buffering). This is | 91 // pictures have been fed to saturate any internal buffering). This is |
92 // speculative and it's unclear that this would be a win (nor that there's a | 92 // speculative and it's unclear that this would be a win (nor that there's a |
93 // reasonably device-agnostic way to fill in the "believes" above). | 93 // reasonably device-agnostic way to fill in the "believes" above). |
94 return base::TimeDelta::FromMilliseconds(10); | 94 constexpr base::TimeDelta DecodePollDelay = |
95 } | 95 base::TimeDelta::FromMilliseconds(10); |
96 | 96 |
97 static inline const base::TimeDelta NoWaitTimeOut() { | 97 constexpr base::TimeDelta NoWaitTimeOut = base::TimeDelta::FromMicroseconds(0); |
98 return base::TimeDelta::FromMicroseconds(0); | |
99 } | |
100 | 98 |
101 static inline const base::TimeDelta IdleTimerTimeOut() { | 99 constexpr base::TimeDelta IdleTimerTimeOut = base::TimeDelta::FromSeconds(1); |
102 return base::TimeDelta::FromSeconds(1); | |
103 } | |
104 | 100 |
105 // Time between when we notice an error, and when we actually notify somebody. | 101 // Time between when we notice an error, and when we actually notify somebody. |
106 // This is to prevent codec errors caused by SurfaceView fullscreen transitions | 102 // This is to prevent codec errors caused by SurfaceView fullscreen transitions |
107 // from breaking the pipeline, if we're about to be reset anyway. | 103 // from breaking the pipeline, if we're about to be reset anyway. |
108 static inline const base::TimeDelta ErrorPostingDelay() { | 104 constexpr base::TimeDelta ErrorPostingDelay = base::TimeDelta::FromSeconds(2); |
109 return base::TimeDelta::FromSeconds(2); | |
110 } | |
111 | 105 |
112 // For RecordFormatChangedMetric. | 106 // For RecordFormatChangedMetric. |
113 enum FormatChangedValue { | 107 enum FormatChangedValue { |
114 CodecInitialized = false, | 108 CodecInitialized = false, |
115 MissingFormatChanged = true | 109 MissingFormatChanged = true |
116 }; | 110 }; |
117 | 111 |
118 // Maximum number of concurrent, incomplete codec creations that we'll allow | 112 // Maximum number of concurrent, incomplete codec creations that we'll allow |
119 // before turning off autodection of codec type. | 113 // before turning off autodection of codec type. |
120 enum { kMaxConcurrentCodecAutodetections = 4 }; | 114 enum { kMaxConcurrentCodecAutodetections = 4 }; |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 // will stay running until we try to shut it down again. | 211 // will stay running until we try to shut it down again. |
218 base::AutoLock auto_lock(autodetection_info_.lock_); | 212 base::AutoLock auto_lock(autodetection_info_.lock_); |
219 if (autodetection_info_.outstanding_) | 213 if (autodetection_info_.outstanding_) |
220 return; | 214 return; |
221 | 215 |
222 construction_thread_.Stop(); | 216 construction_thread_.Stop(); |
223 } | 217 } |
224 | 218 |
225 // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if | 219 // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if |
226 // the instance is already registered and the timer started. The first request | 220 // the instance is already registered and the timer started. The first request |
227 // will start the repeating timer on an interval of DecodePollDelay(). | 221 // will start the repeating timer on an interval of DecodePollDelay. |
228 void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) { | 222 void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) { |
229 DCHECK(thread_checker_.CalledOnValidThread()); | 223 DCHECK(thread_checker_.CalledOnValidThread()); |
230 | 224 |
231 timer_avda_instances_.insert(avda_instance); | 225 timer_avda_instances_.insert(avda_instance); |
232 | 226 |
233 // If the timer is running, StopTimer() might have been called earlier, if | 227 // If the timer is running, StopTimer() might have been called earlier, if |
234 // so remove the instance from the pending erasures. | 228 // so remove the instance from the pending erasures. |
235 if (timer_running_) | 229 if (timer_running_) |
236 pending_erase_.erase(avda_instance); | 230 pending_erase_.erase(avda_instance); |
237 | 231 |
238 if (io_timer_.IsRunning()) | 232 if (io_timer_.IsRunning()) |
239 return; | 233 return; |
240 io_timer_.Start(FROM_HERE, DecodePollDelay(), this, | 234 io_timer_.Start(FROM_HERE, DecodePollDelay, this, |
241 &AVDATimerManager::RunTimer); | 235 &AVDATimerManager::RunTimer); |
242 } | 236 } |
243 | 237 |
244 // Stop callbacks to |avda_instance|->DoIOTask(). Does nothing if the instance | 238 // Stop callbacks to |avda_instance|->DoIOTask(). Does nothing if the instance |
245 // is not registered. If there are no instances left, the repeating timer will | 239 // is not registered. If there are no instances left, the repeating timer will |
246 // be stopped. | 240 // be stopped. |
247 void StopTimer(AndroidVideoDecodeAccelerator* avda_instance) { | 241 void StopTimer(AndroidVideoDecodeAccelerator* avda_instance) { |
248 DCHECK(thread_checker_.CalledOnValidThread()); | 242 DCHECK(thread_checker_.CalledOnValidThread()); |
249 | 243 |
250 // If the timer is running, defer erasures to avoid iterator invalidation. | 244 // If the timer is running, defer erasures to avoid iterator invalidation. |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 if (pending_bitstream_records_.empty()) | 635 if (pending_bitstream_records_.empty()) |
642 return false; | 636 return false; |
643 | 637 |
644 int input_buf_index = pending_input_buf_index_; | 638 int input_buf_index = pending_input_buf_index_; |
645 | 639 |
646 // Do not dequeue a new input buffer if we failed with MEDIA_CODEC_NO_KEY. | 640 // Do not dequeue a new input buffer if we failed with MEDIA_CODEC_NO_KEY. |
647 // That status does not return this buffer back to the pool of | 641 // That status does not return this buffer back to the pool of |
648 // available input buffers. We have to reuse it in QueueSecureInputBuffer(). | 642 // available input buffers. We have to reuse it in QueueSecureInputBuffer(). |
649 if (input_buf_index == -1) { | 643 if (input_buf_index == -1) { |
650 MediaCodecStatus status = | 644 MediaCodecStatus status = |
651 media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index); | 645 media_codec_->DequeueInputBuffer(NoWaitTimeOut, &input_buf_index); |
652 switch (status) { | 646 switch (status) { |
653 case MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER: | 647 case MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER: |
654 return false; | 648 return false; |
655 case MEDIA_CODEC_ERROR: | 649 case MEDIA_CODEC_ERROR: |
656 POST_ERROR(PLATFORM_FAILURE, "Failed to DequeueInputBuffer"); | 650 POST_ERROR(PLATFORM_FAILURE, "Failed to DequeueInputBuffer"); |
657 return false; | 651 return false; |
658 case MEDIA_CODEC_OK: | 652 case MEDIA_CODEC_OK: |
659 break; | 653 break; |
660 default: | 654 default: |
661 NOTREACHED() << "Unknown DequeueInputBuffer status " << status; | 655 NOTREACHED() << "Unknown DequeueInputBuffer status " << status; |
(...skipping 23 matching lines...) Expand all Loading... |
685 shm = std::move(pending_bitstream_records_.front().memory); | 679 shm = std::move(pending_bitstream_records_.front().memory); |
686 | 680 |
687 if (!shm->Map()) { | 681 if (!shm->Map()) { |
688 POST_ERROR(UNREADABLE_INPUT, "Failed to SharedMemoryRegion::Map()"); | 682 POST_ERROR(UNREADABLE_INPUT, "Failed to SharedMemoryRegion::Map()"); |
689 return false; | 683 return false; |
690 } | 684 } |
691 } | 685 } |
692 | 686 |
693 const base::TimeDelta presentation_timestamp = | 687 const base::TimeDelta presentation_timestamp = |
694 bitstream_buffer.presentation_timestamp(); | 688 bitstream_buffer.presentation_timestamp(); |
695 DCHECK(presentation_timestamp != kNoTimestamp()) | 689 DCHECK(presentation_timestamp != kNoTimestamp) |
696 << "Bitstream buffers must have valid presentation timestamps"; | 690 << "Bitstream buffers must have valid presentation timestamps"; |
697 | 691 |
698 // There may already be a bitstream buffer with this timestamp, e.g., VP9 alt | 692 // There may already be a bitstream buffer with this timestamp, e.g., VP9 alt |
699 // ref frames, but it's OK to overwrite it because we only expect a single | 693 // ref frames, but it's OK to overwrite it because we only expect a single |
700 // output frame to have that timestamp. AVDA clients only use the bitstream | 694 // output frame to have that timestamp. AVDA clients only use the bitstream |
701 // buffer id in the returned Pictures to map a bitstream buffer back to a | 695 // buffer id in the returned Pictures to map a bitstream buffer back to a |
702 // timestamp on their side, so either one of the bitstream buffer ids will | 696 // timestamp on their side, so either one of the bitstream buffer ids will |
703 // result in them finding the right timestamp. | 697 // result in them finding the right timestamp. |
704 bitstream_buffers_in_decoder_[presentation_timestamp] = bitstream_buffer.id(); | 698 bitstream_buffers_in_decoder_[presentation_timestamp] = bitstream_buffer.id(); |
705 | 699 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
775 | 769 |
776 bool eos = false; | 770 bool eos = false; |
777 base::TimeDelta presentation_timestamp; | 771 base::TimeDelta presentation_timestamp; |
778 int32_t buf_index = 0; | 772 int32_t buf_index = 0; |
779 do { | 773 do { |
780 size_t offset = 0; | 774 size_t offset = 0; |
781 size_t size = 0; | 775 size_t size = 0; |
782 | 776 |
783 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); | 777 TRACE_EVENT_BEGIN0("media", "AVDA::DequeueOutput"); |
784 MediaCodecStatus status = media_codec_->DequeueOutputBuffer( | 778 MediaCodecStatus status = media_codec_->DequeueOutputBuffer( |
785 NoWaitTimeOut(), &buf_index, &offset, &size, &presentation_timestamp, | 779 NoWaitTimeOut, &buf_index, &offset, &size, &presentation_timestamp, |
786 &eos, NULL); | 780 &eos, NULL); |
787 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, | 781 TRACE_EVENT_END2("media", "AVDA::DequeueOutput", "status", status, |
788 "presentation_timestamp (ms)", | 782 "presentation_timestamp (ms)", |
789 presentation_timestamp.InMilliseconds()); | 783 presentation_timestamp.InMilliseconds()); |
790 | 784 |
791 switch (status) { | 785 switch (status) { |
792 case MEDIA_CODEC_ERROR: | 786 case MEDIA_CODEC_ERROR: |
793 // Do not post an error if we are draining for reset and destroy. | 787 // Do not post an error if we are draining for reset and destroy. |
794 // Instead, run the drain completion task. | 788 // Instead, run the drain completion task. |
795 if (IsDrainingForResetOrDestroy()) { | 789 if (IsDrainingForResetOrDestroy()) { |
(...skipping 730 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1526 strategy_->OnFrameAvailable(); | 1520 strategy_->OnFrameAvailable(); |
1527 } | 1521 } |
1528 | 1522 |
1529 void AndroidVideoDecodeAccelerator::PostError( | 1523 void AndroidVideoDecodeAccelerator::PostError( |
1530 const ::tracked_objects::Location& from_here, | 1524 const ::tracked_objects::Location& from_here, |
1531 VideoDecodeAccelerator::Error error) { | 1525 VideoDecodeAccelerator::Error error) { |
1532 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 1526 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
1533 from_here, | 1527 from_here, |
1534 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, | 1528 base::Bind(&AndroidVideoDecodeAccelerator::NotifyError, |
1535 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), | 1529 weak_this_factory_.GetWeakPtr(), error, error_sequence_token_), |
1536 (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta())); | 1530 (defer_errors_ ? ErrorPostingDelay : base::TimeDelta())); |
1537 state_ = ERROR; | 1531 state_ = ERROR; |
1538 } | 1532 } |
1539 | 1533 |
1540 void AndroidVideoDecodeAccelerator::InitializeCdm() { | 1534 void AndroidVideoDecodeAccelerator::InitializeCdm() { |
1541 DVLOG(2) << __FUNCTION__ << ": " << config_.cdm_id; | 1535 DVLOG(2) << __FUNCTION__ << ": " << config_.cdm_id; |
1542 | 1536 |
1543 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) | 1537 #if !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS) |
1544 NOTIMPLEMENTED(); | 1538 NOTIMPLEMENTED(); |
1545 NotifyInitializationComplete(false); | 1539 NotifyInitializationComplete(false); |
1546 #else | 1540 #else |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1646 if (client_) | 1640 if (client_) |
1647 client_->NotifyError(error); | 1641 client_->NotifyError(error); |
1648 } | 1642 } |
1649 | 1643 |
1650 void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) { | 1644 void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) { |
1651 bool should_be_running = true; | 1645 bool should_be_running = true; |
1652 | 1646 |
1653 base::TimeTicks now = base::TimeTicks::Now(); | 1647 base::TimeTicks now = base::TimeTicks::Now(); |
1654 if (!did_work && !most_recent_work_.is_null()) { | 1648 if (!did_work && !most_recent_work_.is_null()) { |
1655 // Make sure that we have done work recently enough, else stop the timer. | 1649 // Make sure that we have done work recently enough, else stop the timer. |
1656 if (now - most_recent_work_ > IdleTimerTimeOut()) { | 1650 if (now - most_recent_work_ > IdleTimerTimeOut) { |
1657 most_recent_work_ = base::TimeTicks(); | 1651 most_recent_work_ = base::TimeTicks(); |
1658 should_be_running = false; | 1652 should_be_running = false; |
1659 } | 1653 } |
1660 } else { | 1654 } else { |
1661 most_recent_work_ = now; | 1655 most_recent_work_ = now; |
1662 } | 1656 } |
1663 | 1657 |
1664 if (should_be_running) | 1658 if (should_be_running) |
1665 g_avda_timer.Pointer()->StartTimer(this); | 1659 g_avda_timer.Pointer()->StartTimer(this); |
1666 else | 1660 else |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1780 | 1774 |
1781 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() | 1775 bool AndroidVideoDecodeAccelerator::IsMediaCodecSoftwareDecodingForbidden() |
1782 const { | 1776 const { |
1783 // Prevent MediaCodec from using its internal software decoders when we have | 1777 // Prevent MediaCodec from using its internal software decoders when we have |
1784 // more secure and up to date versions in the renderer process. | 1778 // more secure and up to date versions in the renderer process. |
1785 return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 || | 1779 return !config_.is_encrypted && (codec_config_->codec_ == media::kCodecVP8 || |
1786 codec_config_->codec_ == media::kCodecVP9); | 1780 codec_config_->codec_ == media::kCodecVP9); |
1787 } | 1781 } |
1788 | 1782 |
1789 } // namespace media | 1783 } // namespace media |
OLD | NEW |