Index: media/blink/webaudiosourceprovider_impl.cc |
diff --git a/media/blink/webaudiosourceprovider_impl.cc b/media/blink/webaudiosourceprovider_impl.cc |
index 3f052dbeb6f5a8f9759964cb534635f5e19ebd79..c4ddcc10d774098e6d015a4aaaf661221bda9581 100644 |
--- a/media/blink/webaudiosourceprovider_impl.cc |
+++ b/media/blink/webaudiosourceprovider_impl.cc |
@@ -50,18 +50,22 @@ class AutoTryLock { |
// 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. |
+// also holds on 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() : renderer_(nullptr), channels_(0), sample_rate_(0) {} |
~TeeFilter() override {} |
+ void Initialize(AudioRendererSink::RenderCallback* renderer, |
+ int channels, |
+ int sample_rate) { |
+ DCHECK(renderer); |
+ renderer_ = renderer; |
+ channels_ = channels; |
+ sample_rate_ = sample_rate; |
+ } |
+ |
// 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(). |
@@ -70,19 +74,19 @@ class WebAudioSourceProviderImpl::TeeFilter |
uint32_t frames_skipped) override; |
void OnRenderError() override; |
+ bool IsInitialized() const { return !!renderer_; } |
int channels() const { return channels_; } |
int sample_rate() const { return sample_rate_; } |
- void set_copy_audio_bus_callback( |
- const WebAudioSourceProviderImpl::CopyAudioCB& callback) { |
+ void set_copy_audio_bus_callback(const CopyAudioCB& callback) { |
copy_audio_bus_callback_ = callback; |
} |
private: |
- AudioRendererSink::RenderCallback* const renderer_; |
- const int channels_; |
- const int sample_rate_; |
+ AudioRendererSink::RenderCallback* renderer_; |
+ int channels_; |
+ int sample_rate_; |
- WebAudioSourceProviderImpl::CopyAudioCB copy_audio_bus_callback_; |
+ CopyAudioCB copy_audio_bus_callback_; |
DISALLOW_COPY_AND_ASSIGN(TeeFilter); |
}; |
@@ -93,6 +97,7 @@ WebAudioSourceProviderImpl::WebAudioSourceProviderImpl( |
state_(kStopped), |
client_(nullptr), |
sink_(sink), |
+ tee_filter_(new TeeFilter()), |
weak_factory_(this) {} |
WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() { |
@@ -111,12 +116,11 @@ void WebAudioSourceProviderImpl::setClient( |
set_format_cb_ = BindToCurrentLoop(base::Bind( |
&WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr())); |
- // 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_) |
+ // If |tee_filter_| is 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_->IsInitialized()) |
base::ResetAndReturn(&set_format_cb_).Run(); |
} else if (!client && client_) { |
// Restore normal playback. |
@@ -151,7 +155,6 @@ void WebAudioSourceProviderImpl::provideInput( |
} |
DCHECK(client_); |
- 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) |
@@ -221,8 +224,7 @@ void WebAudioSourceProviderImpl::Initialize(const AudioParameters& params, |
base::AutoLock auto_lock(sink_lock_); |
DCHECK_EQ(state_, kStopped); |
- tee_filter_ = base::WrapUnique( |
- new TeeFilter(renderer, params.channels(), params.sample_rate())); |
+ tee_filter_->Initialize(renderer, params.channels(), params.sample_rate()); |
sink_->Initialize(params, tee_filter_.get()); |
@@ -233,6 +235,10 @@ void WebAudioSourceProviderImpl::Initialize(const AudioParameters& params, |
void WebAudioSourceProviderImpl::SetCopyAudioCallback( |
const CopyAudioCB& callback) { |
DCHECK(!callback.is_null()); |
+ |
+ // Use |sink_lock_| to protect |tee_filter_| too since they go in lockstep. |
+ base::AutoLock auto_lock(sink_lock_); |
+ |
DCHECK(tee_filter_); |
tee_filter_->set_copy_audio_bus_callback(callback); |
} |
@@ -242,6 +248,10 @@ void WebAudioSourceProviderImpl::ClearCopyAudioCallback() { |
tee_filter_->set_copy_audio_bus_callback(CopyAudioCB()); |
} |
+int WebAudioSourceProviderImpl::RenderForTesting(AudioBus* audio_bus) { |
+ return tee_filter_->Render(audio_bus, 0, 0); |
+} |
+ |
void WebAudioSourceProviderImpl::OnSetFormat() { |
base::AutoLock auto_lock(sink_lock_); |
if (!client_) |
@@ -251,13 +261,11 @@ void WebAudioSourceProviderImpl::OnSetFormat() { |
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) { |
+ DCHECK(IsInitialized()); |
+ |
const int num_rendered_frames = |
renderer_->Render(audio_bus, delay_milliseconds, frames_skipped); |
@@ -273,6 +281,7 @@ int WebAudioSourceProviderImpl::TeeFilter::Render(AudioBus* audio_bus, |
} |
void WebAudioSourceProviderImpl::TeeFilter::OnRenderError() { |
+ DCHECK(IsInitialized()); |
renderer_->OnRenderError(); |
} |