| Index: third_party/WebKit/Source/platform/audio/AudioDestination.cpp
|
| diff --git a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
|
| index ff053c2dd65a801f89c79d8f8588ba8f724af20e..e71d5ec1d0382f3196048e39545da9686cd543b4 100644
|
| --- a/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
|
| +++ b/third_party/WebKit/Source/platform/audio/AudioDestination.cpp
|
| @@ -29,7 +29,9 @@
|
| #include "platform/audio/AudioDestination.h"
|
|
|
| #include <memory>
|
| +#include "platform/CrossThreadFunctional.h"
|
| #include "platform/Histogram.h"
|
| +#include "platform/WebTaskRunner.h"
|
| #include "platform/audio/AudioUtilities.h"
|
| #include "platform/audio/PushPullFIFO.h"
|
| #include "platform/weborigin/SecurityOrigin.h"
|
| @@ -37,6 +39,7 @@
|
| #include "public/platform/Platform.h"
|
| #include "public/platform/WebAudioLatencyHint.h"
|
| #include "public/platform/WebSecurityOrigin.h"
|
| +#include "public/platform/WebThread.h"
|
|
|
| namespace blink {
|
|
|
| @@ -64,14 +67,16 @@ AudioDestination::AudioDestination(AudioIOCallback& callback,
|
| PassRefPtr<SecurityOrigin> security_origin)
|
| : number_of_output_channels_(number_of_output_channels),
|
| is_playing_(false),
|
| - callback_(callback),
|
| + rendering_thread_(WTF::WrapUnique(
|
| + Platform::Current()->CreateThread("WebAudio Rendering Thread"))),
|
| + fifo_(WTF::WrapUnique(
|
| + new PushPullFIFO(number_of_output_channels, kFIFOSize))),
|
| output_bus_(AudioBus::Create(number_of_output_channels,
|
| AudioUtilities::kRenderQuantumFrames,
|
| false)),
|
| render_bus_(AudioBus::Create(number_of_output_channels,
|
| AudioUtilities::kRenderQuantumFrames)),
|
| - fifo_(WTF::WrapUnique(
|
| - new PushPullFIFO(number_of_output_channels, kFIFOSize))),
|
| + callback_(callback),
|
| frames_elapsed_(0) {
|
| // Create WebAudioDevice. blink::WebAudioDevice is designed to support the
|
| // local input (e.g. loopback from OS audio system), but Chromium's media
|
| @@ -97,6 +102,9 @@ void AudioDestination::Render(const WebVector<float*>& destination_data,
|
| double delay,
|
| double delay_timestamp,
|
| size_t prior_frames_skipped) {
|
| + // This method is called by AudioDeviceThread.
|
| + DCHECK(!IsRenderingThread());
|
| +
|
| CHECK_EQ(destination_data.size(), number_of_output_channels_);
|
| CHECK_EQ(number_of_frames, callback_buffer_size_);
|
|
|
| @@ -106,25 +114,36 @@ void AudioDestination::Render(const WebVector<float*>& destination_data,
|
| if (!fifo_ || fifo_->length() < number_of_frames)
|
| return;
|
|
|
| - frames_elapsed_ -= std::min(frames_elapsed_, prior_frames_skipped);
|
| - double output_position =
|
| - frames_elapsed_ / static_cast<double>(web_audio_device_->SampleRate()) -
|
| - delay;
|
| - output_position_.position = output_position;
|
| - output_position_.timestamp = delay_timestamp;
|
| - output_position_received_timestamp_ = base::TimeTicks::Now();
|
| -
|
| // Associate the destination data array with the output bus then fill the
|
| // FIFO.
|
| for (unsigned i = 0; i < number_of_output_channels_; ++i)
|
| output_bus_->SetChannelMemory(i, destination_data[i], number_of_frames);
|
|
|
| - // Number of frames to render via WebAudio graph. |framesToRender > 0| means
|
| - // the frames in FIFO is not enough to fulfill the requested frames from the
|
| - // audio device.
|
| - size_t frames_to_render = number_of_frames > fifo_->FramesAvailable()
|
| - ? number_of_frames - fifo_->FramesAvailable()
|
| - : 0;
|
| + size_t frames_to_render = fifo_->Pull(output_bus_.Get(), number_of_frames);
|
| +
|
| + rendering_thread_->GetWebTaskRunner()->PostTask(
|
| + BLINK_FROM_HERE,
|
| + CrossThreadBind(&AudioDestination::RequestRenderOnWebThread,
|
| + CrossThreadUnretained(this),
|
| + number_of_frames, frames_to_render,
|
| + delay, delay_timestamp, prior_frames_skipped));
|
| +}
|
| +
|
| +void AudioDestination::RequestRenderOnWebThread(size_t frames_requested,
|
| + size_t frames_to_render,
|
| + double delay,
|
| + double delay_timestamp,
|
| + size_t prior_frames_skipped) {
|
| + // This method is called by WebThread.
|
| + DCHECK(IsRenderingThread());
|
| +
|
| + frames_elapsed_ -= std::min(frames_elapsed_, prior_frames_skipped);
|
| + AudioIOPosition output_position;
|
| + output_position.position =
|
| + frames_elapsed_ / static_cast<double>(web_audio_device_->SampleRate()) -
|
| + delay;
|
| + output_position.timestamp = delay_timestamp;
|
| + base::TimeTicks received_timestamp = base::TimeTicks::Now();
|
|
|
| for (size_t pushed_frames = 0; pushed_frames < frames_to_render;
|
| pushed_frames += AudioUtilities::kRenderQuantumFrames) {
|
| @@ -132,27 +151,23 @@ void AudioDestination::Render(const WebVector<float*>& destination_data,
|
| // 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;
|
| + double delta = (base::TimeTicks::Now() - received_timestamp).InSecondsF();
|
| + output_position.position += delta;
|
| + output_position.timestamp += delta;
|
| }
|
|
|
| // 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;
|
| + if (output_position.position < 0.0)
|
| + output_position.position = 0.0;
|
|
|
| // Process WebAudio graph and push the rendered output to FIFO.
|
| callback_.Render(nullptr, render_bus_.Get(),
|
| - AudioUtilities::kRenderQuantumFrames, output_position_);
|
| + AudioUtilities::kRenderQuantumFrames, output_position);
|
| fifo_->Push(render_bus_.Get());
|
| }
|
|
|
| - fifo_->Pull(output_bus_.Get(), number_of_frames);
|
| -
|
| - frames_elapsed_ += number_of_frames;
|
| + frames_elapsed_ += frames_requested;
|
| }
|
|
|
| void AudioDestination::Start() {
|
| @@ -204,4 +219,9 @@ bool AudioDestination::CheckBufferSize() {
|
| return is_buffer_size_valid;
|
| }
|
|
|
| +bool AudioDestination::IsRenderingThread() {
|
| + return static_cast<ThreadIdentifier>(rendering_thread_->ThreadId()) ==
|
| + CurrentThread();
|
| +}
|
| +
|
| } // namespace blink
|
|
|