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

Side by Side Diff: content/browser/renderer_host/media/audio_renderer_host.cc

Issue 2443573003: Factor out AudioOutputDelegate from AudioRendererHost. (Closed)
Patch Set: Remove [&] from lambda. Created 4 years, 1 month 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/browser/renderer_host/media/audio_renderer_host.h" 5 #include "content/browser/renderer_host/media/audio_renderer_host.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/memory/shared_memory.h"
15 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
16 #include "base/process/process.h" 14 #include "base/process/process.h"
17 #include "content/browser/bad_message.h" 15 #include "content/browser/bad_message.h"
18 #include "content/browser/browser_main_loop.h" 16 #include "content/browser/browser_main_loop.h"
19 #include "content/browser/media/audio_stream_monitor.h" 17 #include "content/browser/media/audio_stream_monitor.h"
20 #include "content/browser/media/capture/audio_mirroring_manager.h" 18 #include "content/browser/media/capture/audio_mirroring_manager.h"
21 #include "content/browser/media/media_devices_permission_checker.h" 19 #include "content/browser/media/media_devices_permission_checker.h"
22 #include "content/browser/media/media_internals.h" 20 #include "content/browser/media/media_internals.h"
23 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 21 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
24 #include "content/browser/renderer_host/media/audio_sync_reader.h" 22 #include "content/browser/renderer_host/media/audio_sync_reader.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 67
70 for (const char& c : device_id) { 68 for (const char& c : device_id) {
71 if ((c < 'a' || c > 'f') && (c < '0' || c > '9')) 69 if ((c < 'a' || c > 'f') && (c < '0' || c > '9'))
72 return false; 70 return false;
73 } 71 }
74 72
75 return true; 73 return true;
76 } 74 }
77 75
78 void NotifyRenderProcessHostThatAudioStateChanged(int render_process_id) { 76 void NotifyRenderProcessHostThatAudioStateChanged(int render_process_id) {
79 DCHECK_CURRENTLY_ON(BrowserThread::UI); 77 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
78 BrowserThread::PostTask(
79 BrowserThread::UI, FROM_HERE,
80 base::Bind(&NotifyRenderProcessHostThatAudioStateChanged,
81 render_process_id));
82 return;
83 }
80 84
81 RenderProcessHost* render_process_host = 85 RenderProcessHost* render_process_host =
82 RenderProcessHost::FromID(render_process_id); 86 RenderProcessHost::FromID(render_process_id);
83 87
84 if (render_process_host) 88 if (render_process_host)
85 render_process_host->AudioStateChanged(); 89 render_process_host->AudioStateChanged();
86 } 90 }
87 91
88 void MaybeFixAudioParameters(media::AudioParameters* params) { 92 void MaybeFixAudioParameters(media::AudioParameters* params) {
89 // If the number of output channels is greater than the maximum, use the 93 // If the number of output channels is greater than the maximum, use the
(...skipping 22 matching lines...) Expand all
112 const base::Callback<void(bool)>& callback) { 116 const base::Callback<void(bool)>& callback) {
113 DCHECK_CURRENTLY_ON(BrowserThread::UI); 117 DCHECK_CURRENTLY_ON(BrowserThread::UI);
114 const bool frame_exists = 118 const bool frame_exists =
115 !!RenderFrameHost::FromID(render_process_id, render_frame_id); 119 !!RenderFrameHost::FromID(render_process_id, render_frame_id);
116 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 120 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
117 base::Bind(callback, frame_exists)); 121 base::Bind(callback, frame_exists));
118 } 122 }
119 123
120 } // namespace 124 } // namespace
121 125
122 class AudioRendererHost::AudioEntry
123 : public media::AudioOutputController::EventHandler {
124 public:
125 ~AudioEntry() override;
126
127 // Returns nullptr on failure.
128 static std::unique_ptr<AudioRendererHost::AudioEntry> Create(
129 AudioRendererHost* host,
130 int stream_id,
131 int render_frame_id,
132 const media::AudioParameters& params,
133 const std::string& output_device_id);
134
135 int stream_id() const {
136 return stream_id_;
137 }
138
139 int render_frame_id() const { return render_frame_id_; }
140
141 media::AudioOutputController* controller() const { return controller_.get(); }
142
143 AudioSyncReader* reader() const { return reader_.get(); }
144
145 // Used by ARH to track the number of active streams for UMA stats.
146 bool playing() const { return playing_; }
147 void set_playing(bool playing) { playing_ = playing; }
148
149 private:
150 AudioEntry(AudioRendererHost* host,
151 int stream_id,
152 int render_frame_id,
153 const media::AudioParameters& params,
154 const std::string& output_device_id,
155 std::unique_ptr<AudioSyncReader> reader);
156
157 // media::AudioOutputController::EventHandler implementation.
158 void OnCreated() override;
159 void OnPlaying() override;
160 void OnPaused() override;
161 void OnError() override;
162
163 AudioRendererHost* const host_;
164 const int stream_id_;
165
166 // The routing ID of the source RenderFrame.
167 const int render_frame_id_;
168
169 // The synchronous reader to be used by |controller_|.
170 const std::unique_ptr<AudioSyncReader> reader_;
171
172 // The AudioOutputController that manages the audio stream.
173 const scoped_refptr<media::AudioOutputController> controller_;
174
175 bool playing_;
176
177 DISALLOW_COPY_AND_ASSIGN(AudioEntry);
178 };
179
180 AudioRendererHost::AudioEntry::AudioEntry(
181 AudioRendererHost* host,
182 int stream_id,
183 int render_frame_id,
184 const media::AudioParameters& params,
185 const std::string& output_device_id,
186 std::unique_ptr<AudioSyncReader> reader)
187 : host_(host),
188 stream_id_(stream_id),
189 render_frame_id_(render_frame_id),
190 reader_(std::move(reader)),
191 controller_(media::AudioOutputController::Create(host->audio_manager_,
192 this,
193 params,
194 output_device_id,
195 reader_.get())),
196 playing_(false) {
197 DCHECK(controller_);
198 }
199
200 AudioRendererHost::AudioEntry::~AudioEntry() {}
201
202 // static
203 std::unique_ptr<AudioRendererHost::AudioEntry>
204 AudioRendererHost::AudioEntry::Create(AudioRendererHost* host,
205 int stream_id,
206 int render_frame_id,
207 const media::AudioParameters& params,
208 const std::string& output_device_id) {
209 std::unique_ptr<AudioSyncReader> reader(AudioSyncReader::Create(params));
210 if (!reader) {
211 return nullptr;
212 }
213 return base::WrapUnique(new AudioEntry(host, stream_id, render_frame_id,
214 params, output_device_id,
215 std::move(reader)));
216 }
217
218 /////////////////////////////////////////////////////////////////////////////// 126 ///////////////////////////////////////////////////////////////////////////////
219 // AudioRendererHost implementations. 127 // AudioRendererHost implementations.
220 128
221 AudioRendererHost::AudioRendererHost(int render_process_id, 129 AudioRendererHost::AudioRendererHost(int render_process_id,
222 media::AudioManager* audio_manager, 130 media::AudioManager* audio_manager,
223 AudioMirroringManager* mirroring_manager, 131 AudioMirroringManager* mirroring_manager,
224 MediaInternals* media_internals, 132 media::AudioLogFactory* log_factory,
225 MediaStreamManager* media_stream_manager, 133 MediaStreamManager* media_stream_manager,
226 const std::string& salt) 134 const std::string& salt)
227 : BrowserMessageFilter(AudioMsgStart), 135 : BrowserMessageFilter(AudioMsgStart),
228 render_process_id_(render_process_id), 136 render_process_id_(render_process_id),
229 audio_manager_(audio_manager), 137 audio_manager_(audio_manager),
230 mirroring_manager_(mirroring_manager), 138 mirroring_manager_(mirroring_manager),
231 audio_log_(media_internals->CreateAudioLog( 139 log_factory_(log_factory),
232 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER)),
233 media_stream_manager_(media_stream_manager), 140 media_stream_manager_(media_stream_manager),
234 num_playing_streams_(0), 141 num_playing_streams_(0),
235 salt_(salt), 142 salt_(salt),
236 validate_render_frame_id_function_(&ValidateRenderFrameId), 143 validate_render_frame_id_function_(&ValidateRenderFrameId),
237 max_simultaneous_streams_(0) { 144 max_simultaneous_streams_(0) {
238 DCHECK(audio_manager_); 145 DCHECK(audio_manager_);
239 DCHECK(media_stream_manager_); 146 DCHECK(media_stream_manager_);
240 } 147 }
241 148
242 AudioRendererHost::~AudioRendererHost() { 149 AudioRendererHost::~AudioRendererHost() {
243 DCHECK_CURRENTLY_ON(BrowserThread::IO); 150 DCHECK_CURRENTLY_ON(BrowserThread::IO);
244 CHECK(audio_entries_.empty()); 151 CHECK(delegates_.empty());
245 152
246 // If we had any streams, report UMA stats for the maximum number of 153 // If we had any streams, report UMA stats for the maximum number of
247 // simultaneous streams for this render process and for the whole browser 154 // simultaneous streams for this render process and for the whole browser
248 // process since last reported. 155 // process since last reported.
249 if (max_simultaneous_streams_ > 0) { 156 if (max_simultaneous_streams_ > 0) {
250 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.AudioRendererIpcStreams", 157 UMA_HISTOGRAM_CUSTOM_COUNTS("Media.AudioRendererIpcStreams",
251 max_simultaneous_streams_, 1, 50, 51); 158 max_simultaneous_streams_, 1, 50, 51);
252 UMA_HISTOGRAM_CUSTOM_COUNTS( 159 UMA_HISTOGRAM_CUSTOM_COUNTS(
253 "Media.AudioRendererIpcStreamsTotal", 160 "Media.AudioRendererIpcStreamsTotal",
254 g_audio_streams_tracker.Get().max_stream_count(), 161 g_audio_streams_tracker.Get().max_stream_count(),
255 1, 100, 101); 162 1, 100, 101);
256 g_audio_streams_tracker.Get().ResetMaxStreamCount(); 163 g_audio_streams_tracker.Get().ResetMaxStreamCount();
257 } 164 }
258 } 165 }
259 166
260 void AudioRendererHost::GetOutputControllers( 167 void AudioRendererHost::GetOutputControllers(
261 const RenderProcessHost::GetAudioOutputControllersCallback& 168 const RenderProcessHost::GetAudioOutputControllersCallback&
262 callback) const { 169 callback) const {
263 BrowserThread::PostTaskAndReplyWithResult( 170 BrowserThread::PostTaskAndReplyWithResult(
264 BrowserThread::IO, FROM_HERE, 171 BrowserThread::IO, FROM_HERE,
265 base::Bind(&AudioRendererHost::DoGetOutputControllers, this), callback); 172 base::Bind(&AudioRendererHost::DoGetOutputControllers, this), callback);
266 } 173 }
267 174
268 void AudioRendererHost::OnChannelClosing() { 175 void AudioRendererHost::OnChannelClosing() {
269 DCHECK_CURRENTLY_ON(BrowserThread::IO); 176 DCHECK_CURRENTLY_ON(BrowserThread::IO);
270 // Since the IPC sender is gone, close all requested audio streams. 177 // Since the IPC sender is gone, close all requested audio streams.
271 while (!audio_entries_.empty()) { 178 for (size_t i = 0; i < delegates_.size(); ++i)
272 // Note: OnCloseStream() removes the entries from audio_entries_. 179 g_audio_streams_tracker.Get().DecreaseStreamCount();
273 OnCloseStream(audio_entries_.begin()->first); 180 delegates_.clear();
274 }
275 181
276 // Remove any authorizations for streams that were not yet created 182 // Remove any authorizations for streams that were not yet created
277 authorizations_.clear(); 183 authorizations_.clear();
278 } 184 }
279 185
280 void AudioRendererHost::OnDestruct() const { 186 void AudioRendererHost::OnDestruct() const {
281 BrowserThread::DeleteOnIOThread::Destruct(this); 187 BrowserThread::DeleteOnIOThread::Destruct(this);
282 } 188 }
283 189
284 void AudioRendererHost::AudioEntry::OnCreated() { 190 void AudioRendererHost::OnStreamCreated(
285 BrowserThread::PostTask( 191 int stream_id,
286 BrowserThread::IO, 192 base::SharedMemory* shared_memory,
287 FROM_HERE, 193 base::CancelableSyncSocket* foreign_socket) {
288 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_));
289 }
290
291 void AudioRendererHost::AudioEntry::OnPlaying() {
292 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
293 base::Bind(&AudioRendererHost::StreamStateChanged,
294 host_, stream_id_, true));
295 }
296
297 void AudioRendererHost::AudioEntry::OnPaused() {
298 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
299 base::Bind(&AudioRendererHost::StreamStateChanged,
300 host_, stream_id_, false));
301 }
302
303 void AudioRendererHost::AudioEntry::OnError() {
304 BrowserThread::PostTask(
305 BrowserThread::IO,
306 FROM_HERE,
307 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_));
308 }
309
310 void AudioRendererHost::DoCompleteCreation(int stream_id) {
311 DCHECK_CURRENTLY_ON(BrowserThread::IO); 194 DCHECK_CURRENTLY_ON(BrowserThread::IO);
312 195
313 if (!PeerHandle()) { 196 if (!PeerHandle()) {
314 DLOG(WARNING) << "Renderer process handle is invalid."; 197 DLOG(WARNING) << "Renderer process handle is invalid.";
315 ReportErrorAndClose(stream_id); 198 OnStreamError(stream_id);
316 return; 199 return;
317 } 200 }
318 201
319 AudioEntry* const entry = LookupById(stream_id); 202 if (!LookupById(stream_id)) {
320 if (!entry) { 203 SendErrorMessage(stream_id);
321 ReportErrorAndClose(stream_id);
322 return; 204 return;
323 } 205 }
324 206
325 // Now construction is done and we are ready to send the shared memory and the
326 // sync socket to the renderer.
327 base::SharedMemory* shared_memory = entry->reader()->shared_memory();
328 base::CancelableSyncSocket* foreign_socket =
329 entry->reader()->foreign_socket();
330
331 base::SharedMemoryHandle foreign_memory_handle; 207 base::SharedMemoryHandle foreign_memory_handle;
332 base::SyncSocket::TransitDescriptor socket_descriptor; 208 base::SyncSocket::TransitDescriptor socket_descriptor;
333 size_t shared_memory_size = shared_memory->requested_size(); 209 size_t shared_memory_size = shared_memory->requested_size();
334 210
211 // TODO(maxmorin): Figure out how/if this is safe, since shared_memory is also
212 // accessed on the audio thread.
335 if (!(shared_memory->ShareToProcess(PeerHandle(), &foreign_memory_handle) && 213 if (!(shared_memory->ShareToProcess(PeerHandle(), &foreign_memory_handle) &&
336 foreign_socket->PrepareTransitDescriptor(PeerHandle(), 214 foreign_socket->PrepareTransitDescriptor(PeerHandle(),
337 &socket_descriptor))) { 215 &socket_descriptor))) {
338 // Something went wrong in preparing the IPC handles. 216 // Something went wrong in preparing the IPC handles.
339 ReportErrorAndClose(entry->stream_id()); 217 OnStreamError(stream_id);
340 return; 218 return;
341 } 219 }
342 220
343 Send(new AudioMsg_NotifyStreamCreated( 221 Send(new AudioMsg_NotifyStreamCreated(
344 stream_id, foreign_memory_handle, socket_descriptor, 222 stream_id, foreign_memory_handle, socket_descriptor,
345 base::checked_cast<uint32_t>(shared_memory_size))); 223 base::checked_cast<uint32_t>(shared_memory_size)));
346 } 224 }
347 225
226 void AudioRendererHost::OnStreamStateChanged(bool is_playing) {
227 DCHECK_CURRENTLY_ON(BrowserThread::IO);
228 if (is_playing) {
229 base::AtomicRefCountInc(&num_playing_streams_);
230
231 // Inform the RenderProcessHost when audio starts playing for the first
232 // time. The nonatomic increment-and-read is ok since this is the only
233 // thread that |num_plaing_streams| may be updated on.
234 if (base::AtomicRefCountIsOne(&num_playing_streams_))
235 NotifyRenderProcessHostThatAudioStateChanged(render_process_id_);
236 } else {
237 // Inform the RenderProcessHost when there is no more audio playing.
238 if (!base::AtomicRefCountDec(&num_playing_streams_))
239 NotifyRenderProcessHostThatAudioStateChanged(render_process_id_);
240 }
241 }
242
243 void AudioRendererHost::OnStreamError(int stream_id) {
244 DCHECK_CURRENTLY_ON(BrowserThread::IO);
245
246 SendErrorMessage(stream_id);
247
248 OnCloseStream(stream_id);
249 }
250
348 void AudioRendererHost::DidValidateRenderFrame(int stream_id, bool is_valid) { 251 void AudioRendererHost::DidValidateRenderFrame(int stream_id, bool is_valid) {
349 DCHECK_CURRENTLY_ON(BrowserThread::IO); 252 DCHECK_CURRENTLY_ON(BrowserThread::IO);
350 253
351 if (!is_valid) { 254 if (!is_valid) {
352 DLOG(WARNING) << "Render frame for stream (id=" << stream_id 255 DLOG(WARNING) << "Render frame for stream (id=" << stream_id
353 << ") no longer exists."; 256 << ") no longer exists.";
354 ReportErrorAndClose(stream_id); 257 OnStreamError(stream_id);
355 } 258 }
356 } 259 }
357 260
358 void AudioRendererHost::StreamStateChanged(int stream_id, bool is_playing) {
359 DCHECK_CURRENTLY_ON(BrowserThread::IO);
360
361 AudioEntry* const entry = LookupById(stream_id);
362 if (!entry)
363 return;
364
365 if (is_playing) {
366 AudioStreamMonitor::StartMonitoringStream(
367 render_process_id_,
368 entry->render_frame_id(),
369 entry->stream_id(),
370 base::Bind(&media::AudioOutputController::ReadCurrentPowerAndClip,
371 entry->controller()));
372 } else {
373 AudioStreamMonitor::StopMonitoringStream(
374 render_process_id_, entry->render_frame_id(), entry->stream_id());
375 }
376 UpdateNumPlayingStreams(entry, is_playing);
377 }
378
379 RenderProcessHost::AudioOutputControllerList 261 RenderProcessHost::AudioOutputControllerList
380 AudioRendererHost::DoGetOutputControllers() const { 262 AudioRendererHost::DoGetOutputControllers() const {
381 DCHECK_CURRENTLY_ON(BrowserThread::IO); 263 DCHECK_CURRENTLY_ON(BrowserThread::IO);
382 264
383 RenderProcessHost::AudioOutputControllerList controllers; 265 RenderProcessHost::AudioOutputControllerList controllers;
384 for (AudioEntryMap::const_iterator it = audio_entries_.begin(); 266 for (const auto& delegate : delegates_)
385 it != audio_entries_.end(); 267 controllers.push_back(delegate->controller());
386 ++it) {
387 controllers.push_back(it->second->controller());
388 }
389 268
390 return controllers; 269 return controllers;
391 } 270 }
392 271
393 /////////////////////////////////////////////////////////////////////////////// 272 ///////////////////////////////////////////////////////////////////////////////
394 // IPC Messages handler 273 // IPC Messages handler
395 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { 274 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) {
396 bool handled = true; 275 bool handled = true;
397 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) 276 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message)
398 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization, 277 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization,
(...skipping 28 matching lines...) Expand all
427 return; 306 return;
428 307
429 if (!IsValidDeviceId(device_id)) { 308 if (!IsValidDeviceId(device_id)) {
430 UMALogDeviceAuthorizationTime(auth_start_time); 309 UMALogDeviceAuthorizationTime(auth_start_time);
431 Send(new AudioMsg_NotifyDeviceAuthorized( 310 Send(new AudioMsg_NotifyDeviceAuthorized(
432 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, 311 stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
433 media::AudioParameters::UnavailableDeviceParams(), std::string())); 312 media::AudioParameters::UnavailableDeviceParams(), std::string()));
434 return; 313 return;
435 } 314 }
436 315
437 // If |session_id should be used for output device selection and such output 316 // If |session_id| should be used for output device selection and such output
438 // device is found, reuse the input device permissions. 317 // device is found, reuse the input device permissions.
439 if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id, 318 if (media::AudioDeviceDescription::UseSessionIdToSelectDevice(session_id,
440 device_id)) { 319 device_id)) {
441 const StreamDeviceInfo* info = 320 const StreamDeviceInfo* info =
442 media_stream_manager_->audio_input_device_manager() 321 media_stream_manager_->audio_input_device_manager()
443 ->GetOpenedDeviceInfoById(session_id); 322 ->GetOpenedDeviceInfoById(session_id);
444 if (info) { 323 if (info) {
445 media::AudioParameters output_params( 324 media::AudioParameters output_params(
446 media::AudioParameters::AUDIO_PCM_LOW_LATENCY, 325 media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
447 static_cast<media::ChannelLayout>( 326 static_cast<media::ChannelLayout>(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 // to create it now. 365 // to create it now.
487 content::bad_message::ReceivedBadMessage( 366 content::bad_message::ReceivedBadMessage(
488 this, bad_message::ARH_CREATED_STREAM_WITHOUT_AUTHORIZATION); 367 this, bad_message::ARH_CREATED_STREAM_WITHOUT_AUTHORIZATION);
489 return; 368 return;
490 } 369 }
491 device_unique_id.swap(auth_data->second.second); 370 device_unique_id.swap(auth_data->second.second);
492 authorizations_.erase(auth_data); 371 authorizations_.erase(auth_data);
493 } 372 }
494 373
495 // Fail early if either of two sanity-checks fail: 374 // Fail early if either of two sanity-checks fail:
496 // 1. There should not yet exist an AudioEntry for the given |stream_id| 375 // 1. There should not yet exist an AudioOutputDelegate for the given
497 // since the renderer may not create two streams with the same ID. 376 // |stream_id| since the renderer may not create two streams with the
377 // same ID.
498 // 2. An out-of-range render frame ID was provided. Renderers must *always* 378 // 2. An out-of-range render frame ID was provided. Renderers must *always*
499 // specify a valid render frame ID for each audio output they create, as 379 // specify a valid render frame ID for each audio output they create, as
500 // several browser-level features depend on this (e.g., OOM manager, UI 380 // several browser-level features depend on this (e.g., OOM manager, UI
501 // audio indicator, muting, audio capture). 381 // audio indicator, muting, audio capture).
502 // Note: media::AudioParameters is validated in the deserializer, so there is 382 // Note: media::AudioParameters is validated in the deserializer, so there is
503 // no need to check that here. 383 // no need to check that here.
504 if (LookupById(stream_id)) { 384 if (LookupById(stream_id)) {
505 SendErrorMessage(stream_id); 385 SendErrorMessage(stream_id);
506 return; 386 return;
507 } 387 }
508 if (render_frame_id <= 0) { 388 if (render_frame_id <= 0) {
509 SendErrorMessage(stream_id); 389 SendErrorMessage(stream_id);
510 return; 390 return;
511 } 391 }
512 392
513 // Post a task to the UI thread to check that the |render_frame_id| references 393 // Post a task to the UI thread to check that the |render_frame_id| references
514 // a valid render frame. This validation is important for all the reasons 394 // a valid render frame. This validation is important for all the reasons
515 // stated in the comments above. This does not block stream creation, but will 395 // stated in the comments above. This does not block stream creation, but will
516 // force-close the stream later if validation fails. 396 // force-close the stream later if validation fails.
517 BrowserThread::PostTask( 397 BrowserThread::PostTask(
518 BrowserThread::UI, FROM_HERE, 398 BrowserThread::UI, FROM_HERE,
519 base::Bind(validate_render_frame_id_function_, render_process_id_, 399 base::Bind(validate_render_frame_id_function_, render_process_id_,
520 render_frame_id, 400 render_frame_id,
521 base::Bind(&AudioRendererHost::DidValidateRenderFrame, this, 401 base::Bind(&AudioRendererHost::DidValidateRenderFrame, this,
522 stream_id))); 402 stream_id)));
523 403
524 std::unique_ptr<AudioEntry> entry = AudioEntry::Create(
525 this, stream_id, render_frame_id, params, device_unique_id);
526 if (!entry) {
527 SendErrorMessage(stream_id);
528 return;
529 }
530
531 MediaObserver* const media_observer = 404 MediaObserver* const media_observer =
532 GetContentClient()->browser()->GetMediaObserver(); 405 GetContentClient()->browser()->GetMediaObserver();
533 if (media_observer)
534 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
535 406
536 if (mirroring_manager_) { 407 std::unique_ptr<media::AudioLog> audio_log = log_factory_->CreateAudioLog(
o1ka 2016/11/03 13:39:12 This |log_factory_| is MediaInternals, right (it c
Max Morin 2016/11/18 16:03:42 Done.
537 mirroring_manager_->AddDiverter( 408 media::AudioLogFactory::AUDIO_OUTPUT_CONTROLLER);
538 render_process_id_, entry->render_frame_id(), entry->controller()); 409 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry(
539 } 410 stream_id, render_process_id_, render_frame_id, audio_log.get());
540 audio_entries_.insert(std::make_pair(stream_id, entry.release())); 411 delegates_.push_back(AudioOutputDelegate::Create(
412 this, audio_manager_, std::move(audio_log), mirroring_manager_,
413 media_observer, stream_id, render_frame_id, render_process_id_, params,
414 device_unique_id));
415
541 g_audio_streams_tracker.Get().IncreaseStreamCount(); 416 g_audio_streams_tracker.Get().IncreaseStreamCount();
542 417
543 audio_log_->OnCreated(stream_id, params, device_unique_id); 418 if (delegates_.size() > max_simultaneous_streams_)
544 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( 419 max_simultaneous_streams_ = delegates_.size();
545 stream_id, render_process_id_, render_frame_id, audio_log_.get());
546
547 if (audio_entries_.size() > max_simultaneous_streams_)
548 max_simultaneous_streams_ = audio_entries_.size();
549 } 420 }
550 421
551 void AudioRendererHost::OnPlayStream(int stream_id) { 422 void AudioRendererHost::OnPlayStream(int stream_id) {
552 DCHECK_CURRENTLY_ON(BrowserThread::IO); 423 DCHECK_CURRENTLY_ON(BrowserThread::IO);
553 424
554 AudioEntry* entry = LookupById(stream_id); 425 AudioOutputDelegate* delegate = LookupById(stream_id);
555 if (!entry) { 426 if (!delegate) {
556 SendErrorMessage(stream_id); 427 SendErrorMessage(stream_id);
557 return; 428 return;
558 } 429 }
559 430
560 entry->controller()->Play(); 431 delegate->OnPlayStream();
561 audio_log_->OnStarted(stream_id);
562 } 432 }
563 433
564 void AudioRendererHost::OnPauseStream(int stream_id) { 434 void AudioRendererHost::OnPauseStream(int stream_id) {
565 DCHECK_CURRENTLY_ON(BrowserThread::IO); 435 DCHECK_CURRENTLY_ON(BrowserThread::IO);
566 436
567 AudioEntry* entry = LookupById(stream_id); 437 AudioOutputDelegate* delegate = LookupById(stream_id);
568 if (!entry) { 438 if (!delegate) {
569 SendErrorMessage(stream_id); 439 SendErrorMessage(stream_id);
570 return; 440 return;
571 } 441 }
572 442
573 entry->controller()->Pause(); 443 delegate->OnPauseStream();
574 audio_log_->OnStopped(stream_id);
575 } 444 }
576 445
577 void AudioRendererHost::OnSetVolume(int stream_id, double volume) { 446 void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
578 DCHECK_CURRENTLY_ON(BrowserThread::IO); 447 DCHECK_CURRENTLY_ON(BrowserThread::IO);
579 448
580 AudioEntry* entry = LookupById(stream_id); 449 AudioOutputDelegate* delegate = LookupById(stream_id);
581 if (!entry) { 450 if (!delegate) {
582 SendErrorMessage(stream_id); 451 SendErrorMessage(stream_id);
583 return; 452 return;
584 } 453 }
585 454
586 // Make sure the volume is valid. 455 // Make sure the volume is valid.
587 if (volume < 0 || volume > 1.0) 456 if (volume < 0 || volume > 1.0)
588 return; 457 return;
589 entry->controller()->SetVolume(volume); 458 delegate->OnSetVolume(volume);
590 audio_log_->OnSetVolume(stream_id, volume);
591 } 459 }
592 460
593 void AudioRendererHost::SendErrorMessage(int stream_id) { 461 void AudioRendererHost::SendErrorMessage(int stream_id) {
594 Send(new AudioMsg_NotifyStreamError(stream_id)); 462 Send(new AudioMsg_NotifyStreamError(stream_id));
595 } 463 }
596 464
597 void AudioRendererHost::OnCloseStream(int stream_id) { 465 void AudioRendererHost::OnCloseStream(int stream_id) {
598 DCHECK_CURRENTLY_ON(BrowserThread::IO); 466 DCHECK_CURRENTLY_ON(BrowserThread::IO);
599 authorizations_.erase(stream_id); 467 authorizations_.erase(stream_id);
600 468
601 // Prevent oustanding callbacks from attempting to close/delete the same 469 // Prevent oustanding callbacks from attempting to close/delete the same
602 // AudioEntry twice. 470 // AudioOutputDelegate twice.
603 AudioEntryMap::iterator i = audio_entries_.find(stream_id); 471 auto i = LookupIteratorById(stream_id);
604 if (i == audio_entries_.end()) 472 if (i == delegates_.end())
605 return; 473 return;
606 std::unique_ptr<AudioEntry> entry(i->second); 474
607 audio_entries_.erase(i); 475 std::swap(*i, delegates_.back());
476 delegates_.pop_back();
477
608 g_audio_streams_tracker.Get().DecreaseStreamCount(); 478 g_audio_streams_tracker.Get().DecreaseStreamCount();
609
610 media::AudioOutputController* const controller = entry->controller();
611 controller->Close(
612 base::Bind(&AudioRendererHost::DeleteEntry, this, base::Passed(&entry)));
613 audio_log_->OnClosed(stream_id);
614 } 479 }
615 480
616 void AudioRendererHost::DeleteEntry(std::unique_ptr<AudioEntry> entry) { 481 AudioRendererHost::AudioOutputDelegateList::iterator
482 AudioRendererHost::LookupIteratorById(int stream_id) {
617 DCHECK_CURRENTLY_ON(BrowserThread::IO); 483 DCHECK_CURRENTLY_ON(BrowserThread::IO);
618 484
619 // De-register the controller from the AudioMirroringManager now that the 485 return std::find_if(delegates_.begin(), delegates_.end(),
620 // controller has closed the AudioOutputStream and shut itself down. This 486 [stream_id](const AudioOutputDelegate::UniquePtr& d) {
621 // ensures that calling RemoveDiverter() here won't trigger the controller to 487 return d->stream_id() == stream_id;
622 // re-start the default AudioOutputStream and cause a brief audio blip to come 488 });
623 // out the user's speakers. http://crbug.com/474432
624 if (mirroring_manager_)
625 mirroring_manager_->RemoveDiverter(entry->controller());
626
627 AudioStreamMonitor::StopMonitoringStream(
628 render_process_id_, entry->render_frame_id(), entry->stream_id());
629 UpdateNumPlayingStreams(entry.get(), false);
630 } 489 }
631 490
632 void AudioRendererHost::ReportErrorAndClose(int stream_id) { 491 AudioOutputDelegate* AudioRendererHost::LookupById(int stream_id) {
633 DCHECK_CURRENTLY_ON(BrowserThread::IO); 492 DCHECK_CURRENTLY_ON(BrowserThread::IO);
634 493
635 // Make sure this isn't a stray callback executing after the stream has been 494 auto i = LookupIteratorById(stream_id);
636 // closed, so error notifications aren't sent after clients believe the stream 495 return i != delegates_.end() ? i->get() : nullptr;
637 // is closed.
638 if (!LookupById(stream_id))
639 return;
640
641 SendErrorMessage(stream_id);
642
643 audio_log_->OnError(stream_id);
644 OnCloseStream(stream_id);
645 }
646
647 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
648 DCHECK_CURRENTLY_ON(BrowserThread::IO);
649
650 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
651 return i != audio_entries_.end() ? i->second : NULL;
652 }
653
654 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry,
655 bool is_playing) {
656 DCHECK_CURRENTLY_ON(BrowserThread::IO);
657 if (entry->playing() == is_playing)
658 return;
659
660 if (is_playing) {
661 entry->set_playing(true);
662 base::AtomicRefCountInc(&num_playing_streams_);
663
664 // Inform the RenderProcessHost when audio starts playing for the first
665 // time.
666 if (base::AtomicRefCountIsOne(&num_playing_streams_)) {
667 BrowserThread::PostTask(
668 BrowserThread::UI, FROM_HERE,
669 base::Bind(&NotifyRenderProcessHostThatAudioStateChanged,
670 render_process_id_));
671 }
672 } else {
673 entry->set_playing(false);
674 // Inform the RenderProcessHost when there is no more audio playing.
675 if (!base::AtomicRefCountDec(&num_playing_streams_)) {
676 BrowserThread::PostTask(
677 BrowserThread::UI, FROM_HERE,
678 base::Bind(&NotifyRenderProcessHostThatAudioStateChanged,
679 render_process_id_));
680 }
681 }
682 } 496 }
683 497
684 bool AudioRendererHost::HasActiveAudio() { 498 bool AudioRendererHost::HasActiveAudio() {
685 return !base::AtomicRefCountIsZero(&num_playing_streams_); 499 return !base::AtomicRefCountIsZero(&num_playing_streams_);
686 } 500 }
687 501
688 void AudioRendererHost::CheckOutputDeviceAccess( 502 void AudioRendererHost::CheckOutputDeviceAccess(
689 int render_frame_id, 503 int render_frame_id,
690 const std::string& device_id, 504 const std::string& device_id,
691 const url::Origin& security_origin, 505 const url::Origin& security_origin,
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
831 std::string() /* matched_device_id */)); 645 std::string() /* matched_device_id */));
832 } 646 }
833 647
834 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { 648 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) {
835 DCHECK_CURRENTLY_ON(BrowserThread::IO); 649 DCHECK_CURRENTLY_ON(BrowserThread::IO);
836 const auto& i = authorizations_.find(stream_id); 650 const auto& i = authorizations_.find(stream_id);
837 return i != authorizations_.end(); 651 return i != authorizations_.end();
838 } 652 }
839 653
840 } // namespace content 654 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698