OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "platform/audio/PushPullFIFO.h" | 5 #include "platform/audio/PushPullFIFO.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include "platform/audio/AudioUtilities.h" | 8 #include "platform/audio/AudioUtilities.h" |
9 #include "platform/wtf/PtrUtil.h" | 9 #include "platform/wtf/PtrUtil.h" |
10 | 10 |
11 namespace blink { | 11 namespace blink { |
12 | 12 |
13 namespace { | 13 namespace { |
14 | 14 |
15 // Suppress the warning log if over/underflow happens more than 100 times. | 15 // Suppress the warning log if over/underflow happens more than 100 times. |
16 const unsigned kMaxMessagesToLog = 100; | 16 const unsigned kMaxMessagesToLog = 100; |
17 } | 17 } |
18 | 18 |
19 const size_t PushPullFIFO::kMaxFIFOLength = 65536; | 19 const size_t PushPullFIFO::kMaxFIFOLength = 65536; |
20 | 20 |
21 PushPullFIFO::PushPullFIFO(unsigned number_of_channels, size_t fifo_length) | 21 PushPullFIFO::PushPullFIFO(unsigned number_of_channels, size_t fifo_length) |
22 : fifo_length_(fifo_length), | 22 : fifo_length_(fifo_length) { |
23 frames_available_(0), | |
24 index_read_(0), | |
25 index_write_(0), | |
26 overflow_count_(0), | |
27 underflow_count_(0) { | |
28 CHECK_LE(fifo_length_, kMaxFIFOLength); | 23 CHECK_LE(fifo_length_, kMaxFIFOLength); |
29 fifo_bus_ = AudioBus::Create(number_of_channels, fifo_length_); | 24 fifo_bus_ = AudioBus::Create(number_of_channels, fifo_length_); |
30 } | 25 } |
31 | 26 |
32 PushPullFIFO::~PushPullFIFO() {} | 27 PushPullFIFO::~PushPullFIFO() {} |
33 | 28 |
34 // Push the data from |inputBus| to FIFO. The size of push is determined by | 29 // Push the data from |inputBus| to FIFO. The size of push is determined by |
35 // the length of |inputBus|. | 30 // the length of |inputBus|. |
36 void PushPullFIFO::Push(const AudioBus* input_bus) { | 31 void PushPullFIFO::Push(const AudioBus* input_bus) { |
| 32 MutexLocker locker(lock_); |
| 33 |
37 CHECK(input_bus); | 34 CHECK(input_bus); |
38 CHECK_EQ(input_bus->length(), AudioUtilities::kRenderQuantumFrames); | 35 CHECK_EQ(input_bus->length(), AudioUtilities::kRenderQuantumFrames); |
39 SECURITY_CHECK(input_bus->length() <= fifo_length_); | 36 SECURITY_CHECK(input_bus->length() <= fifo_length_); |
40 SECURITY_CHECK(index_write_ < fifo_length_); | 37 SECURITY_CHECK(index_write_ < fifo_length_); |
41 | 38 |
42 const size_t input_bus_length = input_bus->length(); | 39 const size_t input_bus_length = input_bus->length(); |
43 const size_t remainder = fifo_length_ - index_write_; | 40 const size_t remainder = fifo_length_ - index_write_; |
44 | 41 |
45 for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) { | 42 for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) { |
46 float* fifo_bus_channel = fifo_bus_->Channel(i)->MutableData(); | 43 float* fifo_bus_channel = fifo_bus_->Channel(i)->MutableData(); |
(...skipping 28 matching lines...) Expand all Loading... |
75 } | 72 } |
76 | 73 |
77 // Update the number of frames available in FIFO. | 74 // Update the number of frames available in FIFO. |
78 frames_available_ = | 75 frames_available_ = |
79 std::min(frames_available_ + input_bus_length, fifo_length_); | 76 std::min(frames_available_ + input_bus_length, fifo_length_); |
80 DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_); | 77 DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_); |
81 } | 78 } |
82 | 79 |
83 // Pull the data out of FIFO to |outputBus|. If remaining frame in the FIFO | 80 // Pull the data out of FIFO to |outputBus|. If remaining frame in the FIFO |
84 // is less than the frames to pull, provides remaining frame plus the silence. | 81 // is less than the frames to pull, provides remaining frame plus the silence. |
85 void PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) { | 82 size_t PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) { |
| 83 MutexLocker locker(lock_); |
| 84 |
86 #if OS(ANDROID) | 85 #if OS(ANDROID) |
87 if (!output_bus) { | 86 if (!output_bus) { |
88 // Log when outputBus or FIFO object is invalid. (crbug.com/692423) | 87 // Log when outputBus or FIFO object is invalid. (crbug.com/692423) |
89 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) | 88 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) |
90 << ">] |outputBus| is invalid."; | 89 << ">] |outputBus| is invalid."; |
91 // Silently return to avoid crash. | 90 // Silently return to avoid crash. |
92 return; | 91 return 0; |
93 } | 92 } |
94 | 93 |
95 // The following checks are in place to catch the inexplicable crash. | 94 // The following checks are in place to catch the inexplicable crash. |
96 // (crbug.com/692423) | 95 // (crbug.com/692423) |
97 if (frames_requested > output_bus->length()) { | 96 if (frames_requested > output_bus->length()) { |
98 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) | 97 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) |
99 << ">] framesRequested > outputBus->length() (" | 98 << ">] framesRequested > outputBus->length() (" |
100 << frames_requested << " > " << output_bus->length() << ")"; | 99 << frames_requested << " > " << output_bus->length() << ")"; |
101 } | 100 } |
102 if (frames_requested > fifo_length_) { | 101 if (frames_requested > fifo_length_) { |
103 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) | 102 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) |
104 << ">] framesRequested > m_fifoLength (" << frames_requested | 103 << ">] framesRequested > m_fifoLength (" << frames_requested |
105 << " > " << fifo_length_ << ")"; | 104 << " > " << fifo_length_ << ")"; |
106 } | 105 } |
107 if (index_read_ >= fifo_length_) { | 106 if (index_read_ >= fifo_length_) { |
108 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) | 107 LOG(WARNING) << "[WebAudio/PushPullFIFO::pull <" << static_cast<void*>(this) |
109 << ">] m_indexRead >= m_fifoLength (" << index_read_ | 108 << ">] m_indexRead >= m_fifoLength (" << index_read_ |
110 << " >= " << fifo_length_ << ")"; | 109 << " >= " << fifo_length_ << ")"; |
111 } | 110 } |
112 #endif | 111 #endif |
| 112 |
113 CHECK(output_bus); | 113 CHECK(output_bus); |
114 SECURITY_CHECK(frames_requested <= output_bus->length()); | 114 SECURITY_CHECK(frames_requested <= output_bus->length()); |
115 SECURITY_CHECK(frames_requested <= fifo_length_); | 115 SECURITY_CHECK(frames_requested <= fifo_length_); |
116 SECURITY_CHECK(index_read_ < fifo_length_); | 116 SECURITY_CHECK(index_read_ < fifo_length_); |
117 | 117 |
118 const size_t remainder = fifo_length_ - index_read_; | 118 const size_t remainder = fifo_length_ - index_read_; |
119 const size_t frames_to_fill = std::min(frames_available_, frames_requested); | 119 const size_t frames_to_fill = std::min(frames_available_, frames_requested); |
120 | 120 |
121 for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) { | 121 for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) { |
122 const float* fifo_bus_channel = fifo_bus_->Channel(i)->Data(); | 122 const float* fifo_bus_channel = fifo_bus_->Channel(i)->Data(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 << "underflowCount=" << underflow_count_ | 155 << "underflowCount=" << underflow_count_ |
156 << ", availableFrames=" << frames_available_ | 156 << ", availableFrames=" << frames_available_ |
157 << ", requestedFrames=" << frames_requested | 157 << ", requestedFrames=" << frames_requested |
158 << ", fifoLength=" << fifo_length_ << ")"; | 158 << ", fifoLength=" << fifo_length_ << ")"; |
159 } | 159 } |
160 } | 160 } |
161 | 161 |
162 // Update the number of frames in FIFO. | 162 // Update the number of frames in FIFO. |
163 frames_available_ -= frames_to_fill; | 163 frames_available_ -= frames_to_fill; |
164 DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_); | 164 DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_); |
| 165 |
| 166 // |framesToRender > 0| means the frames in FIFO is not enough to fulfill the |
| 167 // requested frames from the audio device. |
| 168 return frames_requested > frames_available_ |
| 169 ? frames_requested - frames_available_ |
| 170 : 0; |
165 } | 171 } |
166 | 172 |
167 const PushPullFIFOStateForTest PushPullFIFO::GetStateForTest() const { | 173 const PushPullFIFOStateForTest PushPullFIFO::GetStateForTest() const { |
168 return {length(), NumberOfChannels(), FramesAvailable(), index_read_, | 174 return {length(), NumberOfChannels(), frames_available_, index_read_, |
169 index_write_, overflow_count_, underflow_count_}; | 175 index_write_, overflow_count_, underflow_count_}; |
170 } | 176 } |
171 | 177 |
172 } // namespace blink | 178 } // namespace blink |
OLD | NEW |