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

Unified Diff: media/blink/webaudiosourceprovider_impl.cc

Issue 1781043002: media::WebAudioSourceProviderImpl, add support for getting a copy of passing AudioBuses (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: last round of comments from dalecurtis@ Created 4 years, 9 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 | « media/blink/webaudiosourceprovider_impl.h ('k') | media/blink/webaudiosourceprovider_impl_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/blink/webaudiosourceprovider_impl.cc
diff --git a/media/blink/webaudiosourceprovider_impl.cc b/media/blink/webaudiosourceprovider_impl.cc
index 5b70a3091ba7760878c7f5d9f80147af4a1292c6..d43a16fb5b1b927eab078c7fb7f952b02aafe3b6 100644
--- a/media/blink/webaudiosourceprovider_impl.cc
+++ b/media/blink/webaudiosourceprovider_impl.cc
@@ -47,14 +47,50 @@ class AutoTryLock {
} // namespace
+// TeeFilter is a RenderCallback implementation that allows for a client to get
+// a copy of the data being rendered by the |renderer_| on Render(). This class
+// also holds to the necessary audio parameters.
+class WebAudioSourceProviderImpl::TeeFilter
+ : public AudioRendererSink::RenderCallback {
+ public:
+ TeeFilter(AudioRendererSink::RenderCallback* renderer,
+ int channels,
+ int sample_rate)
+ : renderer_(renderer), channels_(channels), sample_rate_(sample_rate) {
+ DCHECK(renderer_);
+ }
+ ~TeeFilter() override {}
+
+ // AudioRendererSink::RenderCallback implementation.
+ // These are forwarders to |renderer_| and are here to allow for a client to
+ // get a copy of the rendered audio by SetCopyAudioCallback().
+ int Render(AudioBus* audio_bus,
+ uint32_t delay_milliseconds,
+ uint32_t frames_skipped) override;
+ void OnRenderError() override;
+
+ int channels() const { return channels_; }
+ int sample_rate() const { return sample_rate_; }
+ void set_copy_audio_bus_callback(
+ const WebAudioSourceProviderImpl::CopyAudioCB& callback) {
+ copy_audio_bus_callback_ = callback;
+ }
+
+ private:
+ AudioRendererSink::RenderCallback* const renderer_;
+ const int channels_;
+ const int sample_rate_;
+
+ WebAudioSourceProviderImpl::CopyAudioCB copy_audio_bus_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(TeeFilter);
+};
+
WebAudioSourceProviderImpl::WebAudioSourceProviderImpl(
const scoped_refptr<RestartableAudioRendererSink>& sink)
- : channels_(0),
- sample_rate_(0),
- volume_(1.0),
+ : volume_(1.0),
state_(kStopped),
- renderer_(NULL),
- client_(NULL),
+ client_(nullptr),
sink_(sink),
weak_factory_(this) {}
@@ -74,16 +110,16 @@ void WebAudioSourceProviderImpl::setClient(
set_format_cb_ = BindToCurrentLoop(base::Bind(
&WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr()));
- // If |renderer_| is set, then run |set_format_cb_| to send |client_|
- // the current format info. If |renderer_| is not set, then |set_format_cb_|
- // will get called when Initialize() is called.
- // Note: Always using |set_format_cb_| ensures we have the same
- // locking order when calling into |client_|.
- if (renderer_)
+ // If |tee_filter_| is set, it means we have been Initialize()d - then run
+ // |set_format_cb_| to send |client_| the current format info. Otherwise
+ // |set_format_cb_| will get called when Initialize() is called.
+ // Note: Always using |set_format_cb_| ensures we have the same locking
+ // order when calling into |client_|.
+ if (tee_filter_)
base::ResetAndReturn(&set_format_cb_).Run();
} else if (!client && client_) {
// Restore normal playback.
- client_ = NULL;
+ client_ = nullptr;
sink_->SetVolume(volume_);
if (state_ >= kStarted)
sink_->Start();
@@ -99,7 +135,8 @@ void WebAudioSourceProviderImpl::provideInput(
bus_wrapper_ = AudioBus::CreateWrapper(static_cast<int>(audio_data.size()));
}
- bus_wrapper_->set_frames(static_cast<int>(number_of_frames));
+ const int incoming_number_of_frames = static_cast<int>(number_of_frames);
+ bus_wrapper_->set_frames(incoming_number_of_frames);
for (size_t i = 0; i < audio_data.size(); ++i)
bus_wrapper_->SetChannelData(static_cast<int>(i), audio_data[i]);
@@ -112,22 +149,19 @@ void WebAudioSourceProviderImpl::provideInput(
return;
}
- DCHECK(renderer_);
DCHECK(client_);
- DCHECK_EQ(channels_, bus_wrapper_->channels());
- const int frames = renderer_->Render(bus_wrapper_.get(), 0, 0);
- if (frames < static_cast<int>(number_of_frames)) {
- bus_wrapper_->ZeroFramesPartial(
- frames,
- static_cast<int>(number_of_frames - frames));
- }
+ DCHECK(tee_filter_);
+ DCHECK_EQ(tee_filter_->channels(), bus_wrapper_->channels());
+ const int frames = tee_filter_->Render(bus_wrapper_.get(), 0, 0);
+ if (frames < incoming_number_of_frames)
+ bus_wrapper_->ZeroFramesPartial(frames, incoming_number_of_frames - frames);
bus_wrapper_->Scale(volume_);
}
void WebAudioSourceProviderImpl::Start() {
base::AutoLock auto_lock(sink_lock_);
- DCHECK(renderer_);
+ DCHECK(tee_filter_);
DCHECK_EQ(state_, kStopped);
state_ = kStarted;
if (!client_)
@@ -170,30 +204,64 @@ OutputDevice* WebAudioSourceProviderImpl::GetOutputDevice() {
return sink_->GetOutputDevice();
}
-void WebAudioSourceProviderImpl::Initialize(
- const AudioParameters& params,
- RenderCallback* renderer) {
+void WebAudioSourceProviderImpl::Initialize(const AudioParameters& params,
+ RenderCallback* renderer) {
base::AutoLock auto_lock(sink_lock_);
- renderer_ = renderer;
-
DCHECK_EQ(state_, kStopped);
- sink_->Initialize(params, renderer);
- // Keep track of the format in case the client hasn't yet been set.
- channels_ = params.channels();
- sample_rate_ = params.sample_rate();
+ tee_filter_ = make_scoped_ptr(
+ new TeeFilter(renderer, params.channels(), params.sample_rate()));
+
+ sink_->Initialize(params, tee_filter_.get());
if (!set_format_cb_.is_null())
base::ResetAndReturn(&set_format_cb_).Run();
}
+void WebAudioSourceProviderImpl::SetCopyAudioCallback(
+ const CopyAudioCB& callback) {
+ DCHECK(!callback.is_null());
+ DCHECK(tee_filter_);
+ tee_filter_->set_copy_audio_bus_callback(callback);
+}
+
+void WebAudioSourceProviderImpl::ClearCopyAudioCallback() {
+ DCHECK(tee_filter_);
+ tee_filter_->set_copy_audio_bus_callback(CopyAudioCB());
+}
+
void WebAudioSourceProviderImpl::OnSetFormat() {
base::AutoLock auto_lock(sink_lock_);
if (!client_)
return;
// Inform Blink about the audio stream format.
- client_->setFormat(channels_, sample_rate_);
+ client_->setFormat(tee_filter_->channels(), tee_filter_->sample_rate());
+}
+
+int WebAudioSourceProviderImpl::RenderForTesting(AudioBus* audio_bus) {
+ return tee_filter_->Render(audio_bus, 0, 0);
+}
+
+int WebAudioSourceProviderImpl::TeeFilter::Render(AudioBus* audio_bus,
+ uint32_t delay_milliseconds,
+ uint32_t frames_skipped) {
+ const int num_rendered_frames =
+ renderer_->Render(audio_bus, delay_milliseconds, frames_skipped);
+
+ if (!copy_audio_bus_callback_.is_null()) {
+ scoped_ptr<AudioBus> bus_copy =
+ AudioBus::Create(audio_bus->channels(), audio_bus->frames());
+ audio_bus->CopyTo(bus_copy.get());
+ copy_audio_bus_callback_.Run(std::move(bus_copy), delay_milliseconds,
+ sample_rate_);
+ }
+
+ return num_rendered_frames;
+}
+
+void WebAudioSourceProviderImpl::TeeFilter::OnRenderError() {
+ renderer_->OnRenderError();
}
} // namespace media
« no previous file with comments | « media/blink/webaudiosourceprovider_impl.h ('k') | media/blink/webaudiosourceprovider_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698