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

Side by Side Diff: media/blink/webaudiosourceprovider_impl.cc

Issue 2014963002: Revert of Reland: MediaCaptureFromElement: add support for audio captureStream(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/blink/webaudiosourceprovider_impl.h" 5 #include "media/blink/webaudiosourceprovider_impl.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 private: 43 private:
44 base::Lock& lock_; 44 base::Lock& lock_;
45 const bool acquired_; 45 const bool acquired_;
46 DISALLOW_COPY_AND_ASSIGN(AutoTryLock); 46 DISALLOW_COPY_AND_ASSIGN(AutoTryLock);
47 }; 47 };
48 48
49 } // namespace 49 } // namespace
50 50
51 // TeeFilter is a RenderCallback implementation that allows for a client to get 51 // TeeFilter is a RenderCallback implementation that allows for a client to get
52 // a copy of the data being rendered by the |renderer_| on Render(). This class 52 // a copy of the data being rendered by the |renderer_| on Render(). This class
53 // also holds on to the necessary audio parameters. 53 // also holds to the necessary audio parameters.
54 class WebAudioSourceProviderImpl::TeeFilter 54 class WebAudioSourceProviderImpl::TeeFilter
55 : public AudioRendererSink::RenderCallback { 55 : public AudioRendererSink::RenderCallback {
56 public: 56 public:
57 TeeFilter() : renderer_(nullptr), channels_(0), sample_rate_(0) {} 57 TeeFilter(AudioRendererSink::RenderCallback* renderer,
58 int channels,
59 int sample_rate)
60 : renderer_(renderer), channels_(channels), sample_rate_(sample_rate) {
61 DCHECK(renderer_);
62 }
58 ~TeeFilter() override {} 63 ~TeeFilter() override {}
59 64
60 void Initialize(AudioRendererSink::RenderCallback* renderer,
61 int channels,
62 int sample_rate) {
63 DCHECK(renderer);
64 renderer_ = renderer;
65 channels_ = channels;
66 sample_rate_ = sample_rate;
67 }
68
69 // AudioRendererSink::RenderCallback implementation. 65 // AudioRendererSink::RenderCallback implementation.
70 // These are forwarders to |renderer_| and are here to allow for a client to 66 // These are forwarders to |renderer_| and are here to allow for a client to
71 // get a copy of the rendered audio by SetCopyAudioCallback(). 67 // get a copy of the rendered audio by SetCopyAudioCallback().
72 int Render(AudioBus* audio_bus, 68 int Render(AudioBus* audio_bus,
73 uint32_t delay_milliseconds, 69 uint32_t delay_milliseconds,
74 uint32_t frames_skipped) override; 70 uint32_t frames_skipped) override;
75 void OnRenderError() override; 71 void OnRenderError() override;
76 72
77 bool IsInitialized() const { return !!renderer_; }
78 int channels() const { return channels_; } 73 int channels() const { return channels_; }
79 int sample_rate() const { return sample_rate_; } 74 int sample_rate() const { return sample_rate_; }
80 void set_copy_audio_bus_callback(const CopyAudioCB& callback) { 75 void set_copy_audio_bus_callback(
76 const WebAudioSourceProviderImpl::CopyAudioCB& callback) {
81 copy_audio_bus_callback_ = callback; 77 copy_audio_bus_callback_ = callback;
82 } 78 }
83 79
84 private: 80 private:
85 AudioRendererSink::RenderCallback* renderer_; 81 AudioRendererSink::RenderCallback* const renderer_;
86 int channels_; 82 const int channels_;
87 int sample_rate_; 83 const int sample_rate_;
88 84
89 CopyAudioCB copy_audio_bus_callback_; 85 WebAudioSourceProviderImpl::CopyAudioCB copy_audio_bus_callback_;
90 86
91 DISALLOW_COPY_AND_ASSIGN(TeeFilter); 87 DISALLOW_COPY_AND_ASSIGN(TeeFilter);
92 }; 88 };
93 89
94 WebAudioSourceProviderImpl::WebAudioSourceProviderImpl( 90 WebAudioSourceProviderImpl::WebAudioSourceProviderImpl(
95 const scoped_refptr<SwitchableAudioRendererSink>& sink) 91 const scoped_refptr<SwitchableAudioRendererSink>& sink)
96 : volume_(1.0), 92 : volume_(1.0),
97 state_(kStopped), 93 state_(kStopped),
98 client_(nullptr), 94 client_(nullptr),
99 sink_(sink), 95 sink_(sink),
100 tee_filter_(new TeeFilter()),
101 weak_factory_(this) {} 96 weak_factory_(this) {}
102 97
103 WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() { 98 WebAudioSourceProviderImpl::~WebAudioSourceProviderImpl() {
104 } 99 }
105 100
106 void WebAudioSourceProviderImpl::setClient( 101 void WebAudioSourceProviderImpl::setClient(
107 blink::WebAudioSourceProviderClient* client) { 102 blink::WebAudioSourceProviderClient* client) {
108 base::AutoLock auto_lock(sink_lock_); 103 base::AutoLock auto_lock(sink_lock_);
109 if (client && client != client_) { 104 if (client && client != client_) {
110 // Detach the audio renderer from normal playback. 105 // Detach the audio renderer from normal playback.
111 sink_->Stop(); 106 sink_->Stop();
112 107
113 // The client will now take control by calling provideInput() periodically. 108 // The client will now take control by calling provideInput() periodically.
114 client_ = client; 109 client_ = client;
115 110
116 set_format_cb_ = BindToCurrentLoop(base::Bind( 111 set_format_cb_ = BindToCurrentLoop(base::Bind(
117 &WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr())); 112 &WebAudioSourceProviderImpl::OnSetFormat, weak_factory_.GetWeakPtr()));
118 113
119 // If |tee_filter_| is Initialize()d - then run |set_format_cb_| to send 114 // If |tee_filter_| is set, it means we have been Initialize()d - then run
120 // |client_| the current format info. Otherwise |set_format_cb_| will get 115 // |set_format_cb_| to send |client_| the current format info. Otherwise
121 // called when Initialize() is called. Note: Always using |set_format_cb_| 116 // |set_format_cb_| will get called when Initialize() is called.
122 // ensures we have the same locking order when calling into |client_|. 117 // Note: Always using |set_format_cb_| ensures we have the same locking
123 if (tee_filter_->IsInitialized()) 118 // order when calling into |client_|.
119 if (tee_filter_)
124 base::ResetAndReturn(&set_format_cb_).Run(); 120 base::ResetAndReturn(&set_format_cb_).Run();
125 } else if (!client && client_) { 121 } else if (!client && client_) {
126 // Restore normal playback. 122 // Restore normal playback.
127 client_ = nullptr; 123 client_ = nullptr;
128 sink_->SetVolume(volume_); 124 sink_->SetVolume(volume_);
129 if (state_ >= kStarted) 125 if (state_ >= kStarted)
130 sink_->Start(); 126 sink_->Start();
131 if (state_ >= kPlaying) 127 if (state_ >= kPlaying)
132 sink_->Play(); 128 sink_->Play();
133 } 129 }
(...skipping 14 matching lines...) Expand all
148 // Use a try lock to avoid contention in the real-time audio thread. 144 // Use a try lock to avoid contention in the real-time audio thread.
149 AutoTryLock auto_try_lock(sink_lock_); 145 AutoTryLock auto_try_lock(sink_lock_);
150 if (!auto_try_lock.locked() || state_ != kPlaying) { 146 if (!auto_try_lock.locked() || state_ != kPlaying) {
151 // Provide silence if we failed to acquire the lock or the source is not 147 // Provide silence if we failed to acquire the lock or the source is not
152 // running. 148 // running.
153 bus_wrapper_->Zero(); 149 bus_wrapper_->Zero();
154 return; 150 return;
155 } 151 }
156 152
157 DCHECK(client_); 153 DCHECK(client_);
154 DCHECK(tee_filter_);
158 DCHECK_EQ(tee_filter_->channels(), bus_wrapper_->channels()); 155 DCHECK_EQ(tee_filter_->channels(), bus_wrapper_->channels());
159 const int frames = tee_filter_->Render(bus_wrapper_.get(), 0, 0); 156 const int frames = tee_filter_->Render(bus_wrapper_.get(), 0, 0);
160 if (frames < incoming_number_of_frames) 157 if (frames < incoming_number_of_frames)
161 bus_wrapper_->ZeroFramesPartial(frames, incoming_number_of_frames - frames); 158 bus_wrapper_->ZeroFramesPartial(frames, incoming_number_of_frames - frames);
162 159
163 bus_wrapper_->Scale(volume_); 160 bus_wrapper_->Scale(volume_);
164 } 161 }
165 162
166 void WebAudioSourceProviderImpl::Start() { 163 void WebAudioSourceProviderImpl::Start() {
167 base::AutoLock auto_lock(sink_lock_); 164 base::AutoLock auto_lock(sink_lock_);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 callback.Run(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); 214 callback.Run(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
218 else 215 else
219 sink_->SwitchOutputDevice(device_id, security_origin, callback); 216 sink_->SwitchOutputDevice(device_id, security_origin, callback);
220 } 217 }
221 218
222 void WebAudioSourceProviderImpl::Initialize(const AudioParameters& params, 219 void WebAudioSourceProviderImpl::Initialize(const AudioParameters& params,
223 RenderCallback* renderer) { 220 RenderCallback* renderer) {
224 base::AutoLock auto_lock(sink_lock_); 221 base::AutoLock auto_lock(sink_lock_);
225 DCHECK_EQ(state_, kStopped); 222 DCHECK_EQ(state_, kStopped);
226 223
227 tee_filter_->Initialize(renderer, params.channels(), params.sample_rate()); 224 tee_filter_ = base::WrapUnique(
225 new TeeFilter(renderer, params.channels(), params.sample_rate()));
228 226
229 sink_->Initialize(params, tee_filter_.get()); 227 sink_->Initialize(params, tee_filter_.get());
230 228
231 if (!set_format_cb_.is_null()) 229 if (!set_format_cb_.is_null())
232 base::ResetAndReturn(&set_format_cb_).Run(); 230 base::ResetAndReturn(&set_format_cb_).Run();
233 } 231 }
234 232
235 void WebAudioSourceProviderImpl::SetCopyAudioCallback( 233 void WebAudioSourceProviderImpl::SetCopyAudioCallback(
236 const CopyAudioCB& callback) { 234 const CopyAudioCB& callback) {
237 DCHECK(!callback.is_null()); 235 DCHECK(!callback.is_null());
238
239 // Use |sink_lock_| to protect |tee_filter_| too since they go in lockstep.
240 base::AutoLock auto_lock(sink_lock_);
241
242 DCHECK(tee_filter_); 236 DCHECK(tee_filter_);
243 tee_filter_->set_copy_audio_bus_callback(callback); 237 tee_filter_->set_copy_audio_bus_callback(callback);
244 } 238 }
245 239
246 void WebAudioSourceProviderImpl::ClearCopyAudioCallback() { 240 void WebAudioSourceProviderImpl::ClearCopyAudioCallback() {
247 DCHECK(tee_filter_); 241 DCHECK(tee_filter_);
248 tee_filter_->set_copy_audio_bus_callback(CopyAudioCB()); 242 tee_filter_->set_copy_audio_bus_callback(CopyAudioCB());
249 } 243 }
250 244
251 int WebAudioSourceProviderImpl::RenderForTesting(AudioBus* audio_bus) {
252 return tee_filter_->Render(audio_bus, 0, 0);
253 }
254
255 void WebAudioSourceProviderImpl::OnSetFormat() { 245 void WebAudioSourceProviderImpl::OnSetFormat() {
256 base::AutoLock auto_lock(sink_lock_); 246 base::AutoLock auto_lock(sink_lock_);
257 if (!client_) 247 if (!client_)
258 return; 248 return;
259 249
260 // Inform Blink about the audio stream format. 250 // Inform Blink about the audio stream format.
261 client_->setFormat(tee_filter_->channels(), tee_filter_->sample_rate()); 251 client_->setFormat(tee_filter_->channels(), tee_filter_->sample_rate());
262 } 252 }
263 253
254 int WebAudioSourceProviderImpl::RenderForTesting(AudioBus* audio_bus) {
255 return tee_filter_->Render(audio_bus, 0, 0);
256 }
257
264 int WebAudioSourceProviderImpl::TeeFilter::Render(AudioBus* audio_bus, 258 int WebAudioSourceProviderImpl::TeeFilter::Render(AudioBus* audio_bus,
265 uint32_t delay_milliseconds, 259 uint32_t delay_milliseconds,
266 uint32_t frames_skipped) { 260 uint32_t frames_skipped) {
267 DCHECK(IsInitialized());
268
269 const int num_rendered_frames = 261 const int num_rendered_frames =
270 renderer_->Render(audio_bus, delay_milliseconds, frames_skipped); 262 renderer_->Render(audio_bus, delay_milliseconds, frames_skipped);
271 263
272 if (!copy_audio_bus_callback_.is_null()) { 264 if (!copy_audio_bus_callback_.is_null()) {
273 std::unique_ptr<AudioBus> bus_copy = 265 std::unique_ptr<AudioBus> bus_copy =
274 AudioBus::Create(audio_bus->channels(), audio_bus->frames()); 266 AudioBus::Create(audio_bus->channels(), audio_bus->frames());
275 audio_bus->CopyTo(bus_copy.get()); 267 audio_bus->CopyTo(bus_copy.get());
276 copy_audio_bus_callback_.Run(std::move(bus_copy), delay_milliseconds, 268 copy_audio_bus_callback_.Run(std::move(bus_copy), delay_milliseconds,
277 sample_rate_); 269 sample_rate_);
278 } 270 }
279 271
280 return num_rendered_frames; 272 return num_rendered_frames;
281 } 273 }
282 274
283 void WebAudioSourceProviderImpl::TeeFilter::OnRenderError() { 275 void WebAudioSourceProviderImpl::TeeFilter::OnRenderError() {
284 DCHECK(IsInitialized());
285 renderer_->OnRenderError(); 276 renderer_->OnRenderError();
286 } 277 }
287 278
288 } // namespace media 279 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698