Chromium Code Reviews| 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 |