Index: third_party/WebKit/Source/platform/audio/PushPullFIFO.cpp |
diff --git a/third_party/WebKit/Source/platform/audio/PushPullFIFO.cpp b/third_party/WebKit/Source/platform/audio/PushPullFIFO.cpp |
index fdfafd7a37b7ebf3252a98ece9924cee92556794..8f9e9b9e7333616fc29415a44da7b42807342ce0 100644 |
--- a/third_party/WebKit/Source/platform/audio/PushPullFIFO.cpp |
+++ b/third_party/WebKit/Source/platform/audio/PushPullFIFO.cpp |
@@ -18,8 +18,13 @@ const unsigned kMaxMessagesToLog = 100; |
const size_t PushPullFIFO::kMaxFIFOLength = 65536; |
-PushPullFIFO::PushPullFIFO(unsigned number_of_channels, size_t fifo_length) |
- : fifo_length_(fifo_length), |
+PushPullFIFO::PushPullFIFO(unsigned number_of_channels, |
+ size_t fifo_length, |
+ ThreadIdentifier rendering_thread_id, |
+ AudioIOCallback& web_audio_render_callback) |
+ : rendering_thread_id_(rendering_thread_id), |
o1ka
2017/04/13 08:36:53
This is too much information for a FIFO.
Also, we
hongchan
2017/04/14 16:31:48
Done.
|
+ web_audio_render_callback_(web_audio_render_callback), |
+ fifo_length_(fifo_length), |
frames_available_(0), |
index_read_(0), |
index_write_(0), |
@@ -27,62 +32,60 @@ PushPullFIFO::PushPullFIFO(unsigned number_of_channels, size_t fifo_length) |
underflow_count_(0) { |
CHECK_LE(fifo_length_, kMaxFIFOLength); |
fifo_bus_ = AudioBus::Create(number_of_channels, fifo_length_); |
+ render_bus_ = AudioBus::Create(number_of_channels, |
+ AudioUtilities::kRenderQuantumFrames); |
} |
PushPullFIFO::~PushPullFIFO() {} |
-// Push the data from |inputBus| to FIFO. The size of push is determined by |
-// the length of |inputBus|. |
-void PushPullFIFO::Push(const AudioBus* input_bus) { |
- CHECK(input_bus); |
- CHECK_EQ(input_bus->length(), AudioUtilities::kRenderQuantumFrames); |
- SECURITY_CHECK(input_bus->length() <= fifo_length_); |
- SECURITY_CHECK(index_write_ < fifo_length_); |
- |
- const size_t input_bus_length = input_bus->length(); |
- const size_t remainder = fifo_length_ - index_write_; |
- |
- for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) { |
- float* fifo_bus_channel = fifo_bus_->Channel(i)->MutableData(); |
- const float* input_bus_channel = input_bus->Channel(i)->Data(); |
- if (remainder >= input_bus_length) { |
- // The remainder is big enough for the input data. |
- memcpy(fifo_bus_channel + index_write_, input_bus_channel, |
- input_bus_length * sizeof(*fifo_bus_channel)); |
- } else { |
- // The input data overflows the remainder size. Wrap around the index. |
- memcpy(fifo_bus_channel + index_write_, input_bus_channel, |
- remainder * sizeof(*fifo_bus_channel)); |
- memcpy(fifo_bus_channel, input_bus_channel + remainder, |
- (input_bus_length - remainder) * sizeof(*fifo_bus_channel)); |
+void PushPullFIFO::FillRequestedFrames(size_t frames_requested, |
+ size_t callback_buffer_size, |
+ AudioIOPosition output_position) { |
+ DCHECK(IsRenderingThread()); |
+ |
+ MutexLocker lock(lock_); |
+ |
+ base::TimeTicks output_position_received_timestamp = base::TimeTicks::Now(); |
+ |
+ size_t frames_to_render = frames_requested > frames_available_ |
+ ? frames_requested - frames_available_ |
+ : 0; |
+ |
+ for (size_t pushed_frames = 0; pushed_frames < frames_to_render; |
+ pushed_frames += AudioUtilities::kRenderQuantumFrames) { |
+ // If platform buffer is more than two times longer than |framesToProcess| |
+ // we do not want output position to get stuck so we promote it |
+ // using the elapsed time from the moment it was initially obtained. |
+ if (callback_buffer_size > AudioUtilities::kRenderQuantumFrames * 2) { |
+ double delta = |
+ (base::TimeTicks::Now() - output_position_received_timestamp) |
+ .InSecondsF(); |
+ output_position.position += delta; |
+ output_position.timestamp += delta; |
} |
- } |
- // Update the write index; wrap it around if necessary. |
- index_write_ = (index_write_ + input_bus_length) % fifo_length_; |
- |
- // In case of overflow, move the |indexRead| to the updated |indexWrite| to |
- // avoid reading overwritten frames by the next pull. |
- if (input_bus_length > fifo_length_ - frames_available_) { |
- index_read_ = index_write_; |
- if (++overflow_count_ < kMaxMessagesToLog) { |
- LOG(WARNING) << "PushPullFIFO: overflow while pushing (" |
- << "overflowCount=" << overflow_count_ |
- << ", availableFrames=" << frames_available_ |
- << ", inputFrames=" << input_bus_length |
- << ", fifoLength=" << fifo_length_ << ")"; |
- } |
+ // Some implementations give only rough estimation of |delay| so |
+ // we might have negative estimation |outputPosition| value. |
+ if (output_position.position < 0.0) |
+ output_position.position = 0.0; |
+ |
+ // Process WebAudio graph and push the rendered output to FIFO. |
+ web_audio_render_callback_.Render(nullptr, |
+ render_bus_.Get(), |
+ AudioUtilities::kRenderQuantumFrames, |
+ output_position); |
+ Push(render_bus_.Get()); |
} |
- |
- // Update the number of frames available in FIFO. |
- frames_available_ = |
- std::min(frames_available_ + input_bus_length, fifo_length_); |
- DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_); |
} |
// Pull the data out of FIFO to |outputBus|. If remaining frame in the FIFO |
// is less than the frames to pull, provides remaining frame plus the silence. |
void PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) { |
+ // This runs on audio device thread. |
+ DCHECK(!IsRenderingThread()); |
+ |
+ MutexLocker lock(lock_); |
+ |
#if OS(ANDROID) |
if (!output_bus) { |
// Log when outputBus or FIFO object is invalid. (crbug.com/692423) |
@@ -110,6 +113,7 @@ void PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) { |
<< " >= " << fifo_length_ << ")"; |
} |
#endif |
+ |
CHECK(output_bus); |
SECURITY_CHECK(frames_requested <= output_bus->length()); |
SECURITY_CHECK(frames_requested <= fifo_length_); |
@@ -164,9 +168,71 @@ void PushPullFIFO::Pull(AudioBus* output_bus, size_t frames_requested) { |
DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_); |
} |
+AudioBus* PushPullFIFO::GetFIFOBusForTest() const { |
+ MutexLocker lock(lock_); |
+ return fifo_bus_.Get(); |
+} |
+ |
const PushPullFIFOStateForTest PushPullFIFO::GetStateForTest() const { |
- return {length(), NumberOfChannels(), FramesAvailable(), index_read_, |
+ return {length(), NumberOfChannels(), frames_available_, index_read_, |
index_write_, overflow_count_, underflow_count_}; |
+ |
+} |
+ |
+bool PushPullFIFO::IsRenderingThread() { |
+ return rendering_thread_id_ == CurrentThread(); |
+} |
+ |
+// Push the data from |inputBus| to FIFO. The size of push is determined by |
+// the length of |inputBus|. |
+void PushPullFIFO::Push(const AudioBus* input_bus) { |
+ // This runs on WebAudio rendering thread. |
+ DCHECK(IsRenderingThread()); |
+ |
+ CHECK(input_bus); |
+ CHECK_EQ(input_bus->length(), AudioUtilities::kRenderQuantumFrames); |
+ SECURITY_CHECK(input_bus->length() <= fifo_length_); |
+ SECURITY_CHECK(index_write_ < fifo_length_); |
+ |
+ const size_t input_bus_length = input_bus->length(); |
+ const size_t remainder = fifo_length_ - index_write_; |
+ |
+ for (unsigned i = 0; i < fifo_bus_->NumberOfChannels(); ++i) { |
+ float* fifo_bus_channel = fifo_bus_->Channel(i)->MutableData(); |
+ const float* input_bus_channel = input_bus->Channel(i)->Data(); |
+ if (remainder >= input_bus_length) { |
+ // The remainder is big enough for the input data. |
+ memcpy(fifo_bus_channel + index_write_, input_bus_channel, |
+ input_bus_length * sizeof(*fifo_bus_channel)); |
+ } else { |
+ // The input data overflows the remainder size. Wrap around the index. |
+ memcpy(fifo_bus_channel + index_write_, input_bus_channel, |
+ remainder * sizeof(*fifo_bus_channel)); |
+ memcpy(fifo_bus_channel, input_bus_channel + remainder, |
+ (input_bus_length - remainder) * sizeof(*fifo_bus_channel)); |
+ } |
+ } |
+ |
+ // Update the write index; wrap it around if necessary. |
+ index_write_ = (index_write_ + input_bus_length) % fifo_length_; |
+ |
+ // In case of overflow, move the |indexRead| to the updated |indexWrite| to |
+ // avoid reading overwritten frames by the next pull. |
+ if (input_bus_length > fifo_length_ - frames_available_) { |
+ index_read_ = index_write_; |
+ if (++overflow_count_ < kMaxMessagesToLog) { |
+ LOG(WARNING) << "PushPullFIFO: overflow while pushing (" |
+ << "overflowCount=" << overflow_count_ |
+ << ", availableFrames=" << frames_available_ |
+ << ", inputFrames=" << input_bus_length |
+ << ", fifoLength=" << fifo_length_ << ")"; |
+ } |
+ } |
+ |
+ // Update the number of frames available in FIFO. |
+ frames_available_ = |
+ std::min(frames_available_ + input_bus_length, fifo_length_); |
+ DCHECK_EQ((index_read_ + frames_available_) % fifo_length_, index_write_); |
} |
} // namespace blink |