Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1211)

Unified Diff: content/renderer/media/renderer_webaudiodevice_impl.cc

Issue 1990303002: Moving FIFO from AudioDestination to RendererWebAudioDeviceImpl (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix for android compilation error Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/renderer/media/renderer_webaudiodevice_impl.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/renderer/media/renderer_webaudiodevice_impl.cc
diff --git a/content/renderer/media/renderer_webaudiodevice_impl.cc b/content/renderer/media/renderer_webaudiodevice_impl.cc
index a9fba3b4e21ec8f451330dc4d22977766a1eed8c..414175ae07f0a1078969676eb79d4a8779e74f59 100644
--- a/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -17,6 +17,7 @@
#include "content/renderer/media/audio_device_factory.h"
#include "content/renderer/render_frame_impl.h"
#include "media/audio/null_audio_sink.h"
+#include "media/base/audio_pull_fifo.h"
#include "media/base/media_switches.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebView.h"
@@ -26,6 +27,30 @@ using blink::WebLocalFrame;
using blink::WebVector;
using blink::WebView;
+namespace {
+
+int CalculateRenderBufferSizer(int default_sink_frames_per_buffer) {
+#if defined(OS_ANDROID)
+ // The optimum low-latency hardware buffer size is usually too small on
+ // Android for WebAudio to render without glitching. So, if it is small, use
+ // a larger size.
+ //
+ // Since WebAudio renders in 128-frame blocks, the small buffer sizes (144 for
+ // a Galaxy Nexus), cause significant processing jitter. Sometimes multiple
+ // blocks will processed, but other times will not be since the WebAudio can't
+ // satisfy the request. By using a larger render buffer size, we smooth out
+ // the jitter.
+ const int kSmallBufferSize = 1024;
+ const int kDefaultCallbackBufferSize = 2048;
+ if (default_sink_frames_per_buffer <= kSmallBufferSize)
+ return kDefaultCallbackBufferSize;
+#endif
+
+ return default_sink_frames_per_buffer;
+}
+
+} // namespace
+
namespace content {
#if defined(OS_ANDROID)
@@ -37,18 +62,16 @@ RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
WebAudioDevice::RenderCallback* callback,
int session_id,
const url::Origin& security_origin)
- : params_(params),
+ : client_params_(params),
client_callback_(callback),
session_id_(session_id),
task_runner_(base::ThreadTaskRunnerHandle::Get()),
null_audio_sink_(new media::NullAudioSink(task_runner_)),
is_using_null_audio_sink_(false),
- first_buffer_after_silence_(media::AudioBus::Create(params_)),
+ first_buffer_after_silence_(media::AudioBus::Create(client_params_)),
is_first_buffer_after_silence_(false),
security_origin_(security_origin) {
DCHECK(client_callback_);
- null_audio_sink_->Initialize(params_, this);
- null_audio_sink_->Start();
}
RendererWebAudioDeviceImpl::~RendererWebAudioDeviceImpl() {
@@ -75,11 +98,22 @@ void RendererWebAudioDeviceImpl::start() {
AudioDeviceFactory::kSourceWebAudio,
render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE,
session_id_, std::string(), security_origin_);
- sink_->Initialize(params_, this);
- sink_->Start();
- sink_->Play();
+
+ // Output basing on default sink buffer size.
+ media::AudioParameters output_params(client_params_);
+ output_params.set_frames_per_buffer(CalculateRenderBufferSizer(
+ sink_->GetOutputDeviceInfo().output_params().frames_per_buffer()));
+
+ CreateFifoIfRequired(output_params.frames_per_buffer());
+
+ null_audio_sink_->Initialize(output_params, this);
+ null_audio_sink_->Start();
start_null_audio_sink_callback_.Reset(
base::Bind(&media::NullAudioSink::Play, null_audio_sink_));
hongchan 2016/05/26 16:43:33 I am ignorant on the renderer code, but why do we
o1ka 2016/05/26 16:47:47 It was introduce in this CL https://codereview.chr
+
+ sink_->Initialize(output_params, this);
+ sink_->Start();
+ sink_->Play();
// Note: Default behavior is to auto-play on start.
}
@@ -97,18 +131,37 @@ void RendererWebAudioDeviceImpl::stop() {
}
double RendererWebAudioDeviceImpl::sampleRate() {
- return params_.sample_rate();
+ return client_params_.sample_rate();
}
int RendererWebAudioDeviceImpl::Render(media::AudioBus* dest,
uint32_t frames_delayed,
uint32_t frames_skipped) {
#if defined(OS_ANDROID)
+ // There can be a race in Render() on Android (https://crbug.com/614978), so
+ // don't try to inject the FIFO dynamically, just rely on the initialization.
+ DCHECK(audio_fifo_ || (dest->frames() == client_params_.frames_per_buffer()));
+#else
+ // Allow Render() to work on varying buffer size.
+ CreateFifoIfRequired(dest->frames());
+#endif
+
+ if (audio_fifo_)
+ audio_fifo_->Consume(dest, dest->frames());
+ else
+ SourceCallback(0, dest);
+
+ return dest->frames();
+}
+
+void RendererWebAudioDeviceImpl::SourceCallback(int fifo_frame_delay,
+ media::AudioBus* dest) {
+#if defined(OS_ANDROID)
if (is_first_buffer_after_silence_) {
DCHECK(!is_using_null_audio_sink_);
first_buffer_after_silence_->CopyTo(dest);
is_first_buffer_after_silence_ = false;
- return dest->frames();
+ return;
}
#endif
// Wrap the output pointers using WebVector.
@@ -140,7 +193,7 @@ int RendererWebAudioDeviceImpl::Render(media::AudioBus* dest,
// Calling sink_->Play() may trigger reentrancy into this
// function, so this should be called at the end.
sink_->Play();
- return dest->frames();
+ return;
}
} else if (!is_using_null_audio_sink_) {
// Called on the audio device thread.
@@ -153,18 +206,30 @@ int RendererWebAudioDeviceImpl::Render(media::AudioBus* dest,
is_using_null_audio_sink_ = true;
// If Stop() is called right after the task is posted, need to cancel
// this task.
- task_runner_->PostDelayedTask(
- FROM_HERE,
- start_null_audio_sink_callback_.callback(),
- params_.GetBufferDuration());
+ task_runner_->PostDelayedTask(FROM_HERE,
+ start_null_audio_sink_callback_.callback(),
+ client_params_.GetBufferDuration());
}
}
#endif
- return dest->frames();
}
void RendererWebAudioDeviceImpl::OnRenderError() {
// TODO(crogers): implement error handling.
}
+void RendererWebAudioDeviceImpl::CreateFifoIfRequired(
+ int render_frames_per_buffer) {
+ if (!audio_fifo_ &&
+ render_frames_per_buffer != client_params_.frames_per_buffer()) {
+ audio_fifo_.reset(new media::AudioPullFifo(
+ client_params_.channels(), client_params_.frames_per_buffer(),
+ base::Bind(&RendererWebAudioDeviceImpl::SourceCallback,
+ base::Unretained(this))));
+ DVLOG(1) << "Client buffer size: " << client_params_.frames_per_buffer()
+ << " output buffer size: " << render_frames_per_buffer
+ << "; fifo injected.";
+ }
+}
+
} // namespace content
« no previous file with comments | « content/renderer/media/renderer_webaudiodevice_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698