Skip to content

Commit

Permalink
Introduce AudioIOCallbackMetric for monitoring rendering performance
Browse files Browse the repository at this point in the history
This change introduces AudioIOCallbackMetric struct to trace the
rendering performance of Platform's AudioDesitnation. Eventually this
will be connected to the WebAudio DevTool drawer.

The new change is specifically for "Render Capacity" in the design doc:
https://docs.google.com/document/d/1TRgzZwp6M7sWL06UO3GYktqrv9TUv4G0QK6Io6VYVzc/edit?pli=1#bookmark=id.iodlb1gx6qpr

Bug: 837323
Change-Id: I92edca6f0afb755c6514b548d6c45d69e9831340
Reviewed-on: https://chromium-review.googlesource.com/c/1372538
Reviewed-by: Kentaro Hara <[email protected]>
Commit-Queue: Hongchan Choi <[email protected]>
Cr-Commit-Position: refs/heads/master@{#616140}
  • Loading branch information
hoch authored and Commit Bot committed Dec 13, 2018
1 parent f678a2c commit d58b7cc
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ BaseAudioContext::BaseAudioContext(Document* document,
periodic_wave_sawtooth_(nullptr),
periodic_wave_triangle_(nullptr),
output_position_(),
callback_metric_(),
task_runner_(document->GetTaskRunner(TaskType::kInternalMedia)) {}

BaseAudioContext::~BaseAudioContext() {
Expand Down Expand Up @@ -666,7 +667,8 @@ void BaseAudioContext::HandleStoppableSourceNodes() {
}

void BaseAudioContext::HandlePreRenderTasks(
const AudioIOPosition& output_position) {
const AudioIOPosition& output_position,
const AudioIOCallbackMetric& metric) {
DCHECK(IsAudioThread());

// At the beginning of every render quantum, try to update the internal
Expand All @@ -684,8 +686,9 @@ void BaseAudioContext::HandlePreRenderTasks(
// Update the dirty state of the listener.
listener()->UpdateState();

// Update output timestamp.
// Update output timestamp and metric.
output_position_ = output_position;
callback_metric_ = metric;

unlock();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,8 @@ class MODULES_EXPORT BaseAudioContext
void NotifySourceNodeFinishedProcessing(AudioHandler*);

// Called at the start of each render quantum.
void HandlePreRenderTasks(const AudioIOPosition& output_position);
void HandlePreRenderTasks(const AudioIOPosition& output_position,
const AudioIOCallbackMetric& metric);

// Called at the end of each render quantum.
void HandlePostRenderTasks(const AudioBus* destination_bus);
Expand Down Expand Up @@ -420,6 +421,7 @@ class MODULES_EXPORT BaseAudioContext
enum { kMaxNumberOfChannels = 32 };

AudioIOPosition output_position_;
AudioIOCallbackMetric callback_metric_;

// The handler associated with the above |destination_node_|.
scoped_refptr<AudioDestinationHandler> destination_handler_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ double DefaultAudioDestinationHandler::SampleRate() const {
void DefaultAudioDestinationHandler::Render(
AudioBus* destination_bus,
uint32_t number_of_frames,
const AudioIOPosition& output_position) {
const AudioIOPosition& output_position,
const AudioIOCallbackMetric& metric) {
TRACE_EVENT0("webaudio", "DefaultAudioDestinationHandler::Render");

// Denormals can seriously hurt performance of audio processing. This will
Expand All @@ -172,7 +173,7 @@ void DefaultAudioDestinationHandler::Render(
return;
}

Context()->HandlePreRenderTasks(output_position);
Context()->HandlePreRenderTasks(output_position, metric);

// Renders the graph by pulling all the input(s) to this node. This will in
// turn pull on their input(s), all the way backwards through the graph.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ class DefaultAudioDestinationHandler final : public AudioDestinationHandler,
// |output_position|.
void Render(AudioBus* destination_bus,
uint32_t number_of_frames,
const AudioIOPosition& output_position) final;
const AudioIOPosition& output_position,
const AudioIOCallbackMetric& metric) final;

// Returns a hadrware callback buffer size from audio infra.
uint32_t GetCallbackBufferSize() const;
Expand Down
16 changes: 13 additions & 3 deletions third_party/blink/renderer/platform/audio/audio_destination.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,20 @@ void AudioDestination::RequestRender(size_t frames_requested,
frames_elapsed_ / static_cast<double>(web_audio_device_->SampleRate()) -
delay;
output_position.timestamp = delay_timestamp;
base::TimeTicks received_timestamp = base::TimeTicks::Now();

base::TimeTicks callback_request = base::TimeTicks::Now();
AudioIOCallbackMetric metric;
metric.callback_interval =
(callback_request - previous_callback_request_).InSecondsF();
metric.render_duration = previous_render_duration_.InSecondsF();

for (size_t pushed_frames = 0; pushed_frames < frames_to_render;
pushed_frames += audio_utilities::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_ > audio_utilities::kRenderQuantumFrames * 2) {
double delta = (base::TimeTicks::Now() - received_timestamp).InSecondsF();
double delta = (base::TimeTicks::Now() - callback_request).InSecondsF();
output_position.position += delta;
output_position.timestamp += delta;
}
Expand All @@ -186,11 +191,16 @@ void AudioDestination::RequestRender(size_t frames_requested,

// Process WebAudio graph and push the rendered output to FIFO.
callback_.Render(render_bus_.get(), audio_utilities::kRenderQuantumFrames,
output_position);
output_position, metric);

fifo_->Push(render_bus_.get());
}

// Update the IO callback metric with information from the current iteration.
// They are will be picked up in the next render request.
previous_callback_request_ = callback_request;
previous_render_duration_ = base::TimeTicks::Now() - callback_request;

frames_elapsed_ += frames_requested;
}

Expand Down
6 changes: 6 additions & 0 deletions third_party/blink/renderer/platform/audio/audio_destination.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ class PLATFORM_EXPORT AudioDestination
// engine. (i.e. DestinationNode)
AudioIOCallback& callback_;

// When the last callback function from the device is called.
base::TimeTicks previous_callback_request_;

// The time duration spent on rendering previous render quanta per callback.
base::TimeDelta previous_render_duration_;

// Accessed by rendering thread.
size_t frames_elapsed_;
};
Expand Down
15 changes: 14 additions & 1 deletion third_party/blink/renderer/platform/audio/audio_io_callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ namespace blink {

class AudioBus;

// For the calculation of "render capacity". The render capacity can be
// calculated by dividing |render_duration| by |callback_interval|.
struct AudioIOCallbackMetric {
// The time interval in seconds between the onset of previous callback
// function and the current one.
double callback_interval;

// The time duration spent on rendering render quanta (i.e. batch pulling of
// audio graph) per a device callback request.
double render_duration;
};

struct AudioIOPosition {
// Audio stream position in seconds.
double position;
Expand All @@ -50,7 +62,8 @@ class AudioIOCallback {
// |destination_bus|.
virtual void Render(AudioBus* destination_bus,
uint32_t frames_to_process,
const AudioIOPosition& output_position) = 0;
const AudioIOPosition& output_position,
const AudioIOCallbackMetric& metric) = 0;

virtual ~AudioIOCallback() = default;
};
Expand Down

0 comments on commit d58b7cc

Please sign in to comment.