OLD | NEW |
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 #if defined(OS_WIN) |
| 10 #include <windows.h> |
| 11 #endif |
9 | 12 |
10 #include "base/bind.h" | 13 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
12 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
13 #include "base/logging.h" | 16 #include "base/logging.h" |
14 #include "base/memory/shared_memory.h" | 17 #include "base/memory/shared_memory.h" |
15 #include "base/metrics/histogram.h" | 18 #include "base/metrics/histogram.h" |
16 #include "base/process/process.h" | 19 #include "base/process/process.h" |
17 #include "content/browser/bad_message.h" | 20 #include "content/browser/bad_message.h" |
18 #include "content/browser/browser_main_loop.h" | 21 #include "content/browser/browser_main_loop.h" |
| 22 #include "content/browser/media/audio_output_impl.h" |
19 #include "content/browser/media/audio_stream_monitor.h" | 23 #include "content/browser/media/audio_stream_monitor.h" |
20 #include "content/browser/media/capture/audio_mirroring_manager.h" | 24 #include "content/browser/media/capture/audio_mirroring_manager.h" |
21 #include "content/browser/media/media_internals.h" | 25 #include "content/browser/media/media_internals.h" |
22 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 26 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
23 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 27 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
24 #include "content/browser/renderer_host/media/media_stream_manager.h" | 28 #include "content/browser/renderer_host/media/media_stream_manager.h" |
25 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" | 29 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" |
26 #include "content/browser/renderer_host/render_widget_host_impl.h" | 30 #include "content/browser/renderer_host/render_widget_host_impl.h" |
27 #include "content/common/media/audio_messages.h" | 31 #include "content/common/media/audio_messages.h" |
28 #include "content/public/browser/content_browser_client.h" | 32 #include "content/public/browser/content_browser_client.h" |
29 #include "content/public/browser/media_device_id.h" | 33 #include "content/public/browser/media_device_id.h" |
30 #include "content/public/browser/media_observer.h" | 34 #include "content/public/browser/media_observer.h" |
31 #include "content/public/browser/render_frame_host.h" | 35 #include "content/public/browser/render_frame_host.h" |
32 #include "content/public/common/content_switches.h" | 36 #include "content/public/common/content_switches.h" |
33 #include "media/audio/audio_device_description.h" | 37 #include "media/audio/audio_device_description.h" |
34 #include "media/audio/audio_streams_tracker.h" | 38 #include "media/audio/audio_streams_tracker.h" |
35 #include "media/base/audio_bus.h" | 39 #include "media/base/audio_bus.h" |
36 #include "media/base/limits.h" | 40 #include "media/base/limits.h" |
| 41 #include "mojo/edk/embedder/embedder.h" |
| 42 #include "mojo/public/cpp/system/handle.h" |
37 | 43 |
38 using media::AudioBus; | 44 using media::AudioBus; |
39 using media::AudioManager; | 45 using media::AudioManager; |
40 | 46 |
41 namespace content { | 47 namespace content { |
42 | 48 |
43 namespace { | 49 namespace { |
44 | 50 |
45 // Tracks the maximum number of simultaneous output streams browser-wide. | 51 // Tracks the maximum number of simultaneous output streams browser-wide. |
46 // Accessed on IO thread. | 52 // Accessed on IO thread. |
47 base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker = | 53 base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker = |
48 LAZY_INSTANCE_INITIALIZER; | 54 LAZY_INSTANCE_INITIALIZER; |
49 | 55 |
50 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData( | 56 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData( |
51 int stream_id, | 57 int stream_id, |
52 bool authorized, | 58 bool authorized, |
53 const std::string& device_unique_id) { | 59 const std::string& device_unique_id) { |
54 return std::make_pair(stream_id, | 60 return std::make_pair(stream_id, |
55 std::make_pair(authorized, device_unique_id)); | 61 std::make_pair(authorized, device_unique_id)); |
56 } | 62 } |
57 | 63 |
| 64 base::SyncSocket::TransitDescriptor DuplicateSocket( |
| 65 base::SyncSocket::TransitDescriptor socket_descriptor) { |
| 66 base::SyncSocket::TransitDescriptor socket_descriptor_dup; |
| 67 |
| 68 #if defined(OS_WIN) |
| 69 socket_descriptor_dup = 0; |
| 70 if (!::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle |
| 71 socket_descriptor, |
| 72 GetCurrentProcess(), // hTargetProcessHandle |
| 73 &socket_descriptor_dup, |
| 74 0, // dwDesiredAccess ignored due to SAME_ACCESS |
| 75 FALSE, // !bInheritHandle |
| 76 DUPLICATE_SAME_ACCESS)) { |
| 77 LOG(ERROR) << "Unable to duplicate socket handle."; |
| 78 } |
| 79 |
| 80 #else |
| 81 socket_descriptor_dup.fd = dup(socket_descriptor.fd); |
| 82 #endif |
| 83 return socket_descriptor_dup; |
| 84 } |
| 85 |
58 bool IsValidDeviceId(const std::string& device_id) { | 86 bool IsValidDeviceId(const std::string& device_id) { |
59 static const std::string::size_type kValidLength = 64; | 87 static const std::string::size_type kValidLength = 64; |
60 | 88 |
61 if (device_id.empty() || | 89 if (device_id.empty() || |
62 device_id == media::AudioDeviceDescription::kDefaultDeviceId || | 90 device_id == media::AudioDeviceDescription::kDefaultDeviceId || |
63 device_id == media::AudioDeviceDescription::kCommunicationsDeviceId) { | 91 device_id == media::AudioDeviceDescription::kCommunicationsDeviceId) { |
64 return true; | 92 return true; |
65 } | 93 } |
66 | 94 |
67 if (device_id.length() != kValidLength) | 95 if (device_id.length() != kValidLength) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 | 141 |
114 class AudioRendererHost::AudioEntry | 142 class AudioRendererHost::AudioEntry |
115 : public media::AudioOutputController::EventHandler { | 143 : public media::AudioOutputController::EventHandler { |
116 public: | 144 public: |
117 AudioEntry(AudioRendererHost* host, | 145 AudioEntry(AudioRendererHost* host, |
118 int stream_id, | 146 int stream_id, |
119 int render_frame_id, | 147 int render_frame_id, |
120 const media::AudioParameters& params, | 148 const media::AudioParameters& params, |
121 const std::string& output_device_id, | 149 const std::string& output_device_id, |
122 std::unique_ptr<base::SharedMemory> shared_memory, | 150 std::unique_ptr<base::SharedMemory> shared_memory, |
123 std::unique_ptr<media::AudioOutputController::SyncReader> reader); | 151 std::unique_ptr<media::AudioOutputController::SyncReader> reader, |
| 152 const media::mojom::AudioOutput::CreateStreamCallback& |
| 153 create_stream_callback); |
124 ~AudioEntry() override; | 154 ~AudioEntry() override; |
125 | 155 |
126 int stream_id() const { | 156 int stream_id() const { |
127 return stream_id_; | 157 return stream_id_; |
128 } | 158 } |
129 | 159 |
130 int render_frame_id() const { return render_frame_id_; } | 160 int render_frame_id() const { return render_frame_id_; } |
131 | 161 |
132 media::AudioOutputController* controller() const { return controller_.get(); } | 162 media::AudioOutputController* controller() const { return controller_.get(); } |
133 | 163 |
134 base::SharedMemory* shared_memory() { | 164 base::SharedMemory* shared_memory() { |
135 return shared_memory_.get(); | 165 return shared_memory_.get(); |
136 } | 166 } |
137 | 167 |
138 media::AudioOutputController::SyncReader* reader() const { | 168 media::AudioOutputController::SyncReader* reader() const { |
139 return reader_.get(); | 169 return reader_.get(); |
140 } | 170 } |
141 | 171 |
142 bool playing() const { return playing_; } | 172 bool playing() const { return playing_; } |
143 void set_playing(bool playing) { playing_ = playing; } | 173 void set_playing(bool playing) { playing_ = playing; } |
144 | 174 |
| 175 media::mojom::AudioOutput::CreateStreamCallback* |
| 176 get_create_stream_callback() { |
| 177 return &create_stream_callback_; |
| 178 } |
| 179 |
145 private: | 180 private: |
146 // media::AudioOutputController::EventHandler implementation. | 181 // media::AudioOutputController::EventHandler implementation. |
147 void OnCreated() override; | 182 void OnCreated() override; |
148 void OnPlaying() override; | 183 void OnPlaying() override; |
149 void OnPaused() override; | 184 void OnPaused() override; |
150 void OnError() override; | 185 void OnError() override; |
151 | 186 |
152 AudioRendererHost* const host_; | 187 AudioRendererHost* const host_; |
153 const int stream_id_; | 188 const int stream_id_; |
154 | 189 |
155 // The routing ID of the source RenderFrame. | 190 // The routing ID of the source RenderFrame. |
156 const int render_frame_id_; | 191 const int render_frame_id_; |
157 | 192 |
158 // Shared memory for transmission of the audio data. Used by |reader_|. | 193 // Shared memory for transmission of the audio data. Used by |reader_|. |
159 const std::unique_ptr<base::SharedMemory> shared_memory_; | 194 const std::unique_ptr<base::SharedMemory> shared_memory_; |
160 | 195 |
161 // The synchronous reader to be used by |controller_|. | 196 // The synchronous reader to be used by |controller_|. |
162 const std::unique_ptr<media::AudioOutputController::SyncReader> reader_; | 197 const std::unique_ptr<media::AudioOutputController::SyncReader> reader_; |
163 | 198 |
164 // The AudioOutputController that manages the audio stream. | 199 // The AudioOutputController that manages the audio stream. |
165 const scoped_refptr<media::AudioOutputController> controller_; | 200 const scoped_refptr<media::AudioOutputController> controller_; |
166 | 201 |
167 bool playing_; | 202 bool playing_; |
| 203 |
| 204 // Callback for media::mojom::AudioOutput::CreateStream. |
| 205 media::mojom::AudioOutput::CreateStreamCallback create_stream_callback_; |
168 }; | 206 }; |
169 | 207 |
170 AudioRendererHost::AudioEntry::AudioEntry( | 208 AudioRendererHost::AudioEntry::AudioEntry( |
171 AudioRendererHost* host, | 209 AudioRendererHost* host, |
172 int stream_id, | 210 int stream_id, |
173 int render_frame_id, | 211 int render_frame_id, |
174 const media::AudioParameters& params, | 212 const media::AudioParameters& params, |
175 const std::string& output_device_id, | 213 const std::string& output_device_id, |
176 std::unique_ptr<base::SharedMemory> shared_memory, | 214 std::unique_ptr<base::SharedMemory> shared_memory, |
177 std::unique_ptr<media::AudioOutputController::SyncReader> reader) | 215 std::unique_ptr<media::AudioOutputController::SyncReader> reader, |
| 216 const media::mojom::AudioOutput::CreateStreamCallback& |
| 217 create_stream_callback) |
178 : host_(host), | 218 : host_(host), |
179 stream_id_(stream_id), | 219 stream_id_(stream_id), |
180 render_frame_id_(render_frame_id), | 220 render_frame_id_(render_frame_id), |
181 shared_memory_(std::move(shared_memory)), | 221 shared_memory_(std::move(shared_memory)), |
182 reader_(std::move(reader)), | 222 reader_(std::move(reader)), |
183 controller_(media::AudioOutputController::Create(host->audio_manager_, | 223 controller_(media::AudioOutputController::Create(host->audio_manager_, |
184 this, | 224 this, |
185 params, | 225 params, |
186 output_device_id, | 226 output_device_id, |
187 reader_.get())), | 227 reader_.get())), |
188 playing_(false) { | 228 playing_(false), |
| 229 create_stream_callback_(create_stream_callback) { |
189 DCHECK(controller_.get()); | 230 DCHECK(controller_.get()); |
190 } | 231 } |
191 | 232 |
192 AudioRendererHost::AudioEntry::~AudioEntry() {} | 233 AudioRendererHost::AudioEntry::~AudioEntry() {} |
193 | 234 |
194 /////////////////////////////////////////////////////////////////////////////// | 235 /////////////////////////////////////////////////////////////////////////////// |
195 // AudioRendererHost implementations. | 236 // AudioRendererHost implementations. |
196 | 237 |
197 AudioRendererHost::AudioRendererHost( | 238 AudioRendererHost::AudioRendererHost( |
198 int render_process_id, | 239 int render_process_id, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 const RenderProcessHost::GetAudioOutputControllersCallback& | 278 const RenderProcessHost::GetAudioOutputControllersCallback& |
238 callback) const { | 279 callback) const { |
239 BrowserThread::PostTaskAndReplyWithResult( | 280 BrowserThread::PostTaskAndReplyWithResult( |
240 BrowserThread::IO, FROM_HERE, | 281 BrowserThread::IO, FROM_HERE, |
241 base::Bind(&AudioRendererHost::DoGetOutputControllers, this), callback); | 282 base::Bind(&AudioRendererHost::DoGetOutputControllers, this), callback); |
242 } | 283 } |
243 | 284 |
244 void AudioRendererHost::OnChannelClosing() { | 285 void AudioRendererHost::OnChannelClosing() { |
245 // Since the IPC sender is gone, close all requested audio streams. | 286 // Since the IPC sender is gone, close all requested audio streams. |
246 while (!audio_entries_.empty()) { | 287 while (!audio_entries_.empty()) { |
247 // Note: OnCloseStream() removes the entries from audio_entries_. | 288 // Note: CloseStream() removes the entries from audio_entries_. |
248 OnCloseStream(audio_entries_.begin()->first); | 289 CloseStream(audio_entries_.begin()->first); |
249 } | 290 } |
250 | 291 |
251 // Remove any authorizations for streams that were not yet created | 292 // Remove any authorizations for streams that were not yet created |
252 authorizations_.clear(); | 293 authorizations_.clear(); |
253 } | 294 } |
254 | 295 |
255 void AudioRendererHost::OnDestruct() const { | 296 void AudioRendererHost::OnDestruct() const { |
256 BrowserThread::DeleteOnIOThread::Destruct(this); | 297 BrowserThread::DeleteOnIOThread::Destruct(this); |
257 } | 298 } |
258 | 299 |
259 void AudioRendererHost::AudioEntry::OnCreated() { | 300 void AudioRendererHost::AudioEntry::OnCreated() { |
260 BrowserThread::PostTask( | 301 BrowserThread::PostTask( |
261 BrowserThread::IO, | 302 BrowserThread::IO, FROM_HERE, |
262 FROM_HERE, | 303 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_, |
263 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_)); | 304 create_stream_callback_)); |
264 } | 305 } |
265 | 306 |
266 void AudioRendererHost::AudioEntry::OnPlaying() { | 307 void AudioRendererHost::AudioEntry::OnPlaying() { |
267 BrowserThread::PostTask( | 308 BrowserThread::PostTask( |
268 BrowserThread::IO, | 309 BrowserThread::IO, |
269 FROM_HERE, | 310 FROM_HERE, |
270 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, | 311 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, |
271 host_, | 312 host_, |
272 stream_id_, | 313 stream_id_, |
273 true)); | 314 true)); |
274 } | 315 } |
275 | 316 |
276 void AudioRendererHost::AudioEntry::OnPaused() { | 317 void AudioRendererHost::AudioEntry::OnPaused() { |
277 BrowserThread::PostTask( | 318 BrowserThread::PostTask( |
278 BrowserThread::IO, | 319 BrowserThread::IO, |
279 FROM_HERE, | 320 FROM_HERE, |
280 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, | 321 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, |
281 host_, | 322 host_, |
282 stream_id_, | 323 stream_id_, |
283 false)); | 324 false)); |
284 } | 325 } |
285 | 326 |
286 void AudioRendererHost::AudioEntry::OnError() { | 327 void AudioRendererHost::AudioEntry::OnError() { |
287 BrowserThread::PostTask( | 328 BrowserThread::PostTask( |
288 BrowserThread::IO, | 329 BrowserThread::IO, |
289 FROM_HERE, | 330 FROM_HERE, |
290 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); | 331 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); |
291 } | 332 } |
292 | 333 |
293 void AudioRendererHost::DoCompleteCreation(int stream_id) { | 334 void AudioRendererHost::DoCompleteCreation( |
| 335 int stream_id, |
| 336 const media::mojom::AudioOutput::CreateStreamCallback& |
| 337 create_stream_callback) { |
294 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 338 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
295 | 339 |
296 if (!PeerHandle()) { | 340 if (!PeerHandle()) { |
297 DLOG(WARNING) << "Renderer process handle is invalid."; | 341 DLOG(WARNING) << "Renderer process handle is invalid."; |
298 ReportErrorAndClose(stream_id); | 342 ReportErrorAndCloseStream(stream_id, create_stream_callback); |
299 return; | 343 return; |
300 } | 344 } |
301 | 345 |
302 AudioEntry* const entry = LookupById(stream_id); | 346 AudioEntry* entry = LookupById(stream_id); |
303 if (!entry) { | 347 if (!entry) { |
304 ReportErrorAndClose(stream_id); | 348 ReportErrorAndCloseStream(stream_id, create_stream_callback); |
305 return; | 349 return; |
306 } | 350 } |
307 | 351 |
308 // Once the audio stream is created then complete the creation process by | 352 media::mojom::AudioOutputStreamPtr stream_ptr = |
309 // mapping shared memory and sharing with the renderer process. | 353 (audio_output_impls_[entry->render_frame_id()]->StreamFactory( |
310 base::SharedMemoryHandle foreign_memory_handle; | 354 stream_id, entry->render_frame_id(), this)); |
311 if (!entry->shared_memory()->ShareToProcess(PeerHandle(), | 355 |
312 &foreign_memory_handle)) { | 356 base::SharedMemoryHandle shared_memory_handle = |
313 // If we failed to map and share the shared memory then close the audio | 357 base::SharedMemory::DuplicateHandle(entry->shared_memory()->handle()); |
314 // stream and send an error message. | 358 |
315 ReportErrorAndClose(entry->stream_id()); | 359 MojoHandle mojo_foreign_memory_handle; |
| 360 |
| 361 MojoResult shared_buffer_result = mojo::edk::CreateSharedBufferWrapper( |
| 362 shared_memory_handle, entry->shared_memory()->requested_size(), false, |
| 363 &mojo_foreign_memory_handle); |
| 364 |
| 365 if (shared_buffer_result != MOJO_RESULT_OK) { |
| 366 DLOG(WARNING) << "Failed to wrap transit descriptor. Closing: " |
| 367 << shared_buffer_result; |
| 368 ReportErrorAndCloseStream(entry->stream_id(), create_stream_callback); |
316 return; | 369 return; |
317 } | 370 } |
318 | 371 |
319 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); | 372 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); |
320 | 373 |
321 base::SyncSocket::TransitDescriptor socket_descriptor; | 374 base::SyncSocket::TransitDescriptor socket_descriptor; |
322 | 375 |
323 // If we failed to prepare the sync socket for the renderer then we fail | 376 // If we failed to prepare the sync socket for the renderer then we fail |
324 // the construction of audio stream. | 377 // the construction of audio stream. |
325 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { | 378 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { |
326 ReportErrorAndClose(entry->stream_id()); | 379 ReportErrorAndCloseStream(entry->stream_id(), create_stream_callback); |
| 380 return; |
| 381 } |
| 382 mojo::ScopedSharedBufferHandle shared_buffer_handle = |
| 383 mojo::ScopedSharedBufferHandle( |
| 384 mojo::SharedBufferHandle(mojo_foreign_memory_handle)); |
| 385 |
| 386 MojoHandle socket_descriptor_handle; |
| 387 MojoResult platform_handle_result; |
| 388 |
| 389 // The socket handle is going to be closed when |mojo_application_host_| is |
| 390 // reset. The renderer is going to need to close the socket handle |
| 391 // too when the output steam is closed. This is going to cause an issue |
| 392 // because both of them are going to close the same socket handle. |
| 393 // This is why a duplicate of the socket handler is going to be created, |
| 394 // stored in |socket_descriptor_dup| and sent through Mojo to the renderer so |
| 395 // it can be used by AudioOutputIPCDelegate. |
| 396 |
| 397 base::SyncSocket::TransitDescriptor socket_descriptor_dup = |
| 398 DuplicateSocket(socket_descriptor); |
| 399 #if defined(OS_WIN) |
| 400 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( |
| 401 mojo::edk::ScopedPlatformHandle( |
| 402 mojo::edk::PlatformHandle(socket_descriptor_dup), |
| 403 &socket_descriptor_handle); |
| 404 #else |
| 405 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( |
| 406 mojo::edk::ScopedPlatformHandle( |
| 407 mojo::edk::PlatformHandle(socket_descriptor_dup.fd)), |
| 408 &socket_descriptor_handle); |
| 409 #endif |
| 410 |
| 411 if (platform_handle_result != MOJO_RESULT_OK) { |
| 412 DLOG(WARNING) << "Failed to wrap platform handle. Closing: " |
| 413 << platform_handle_result; |
| 414 ReportErrorAndCloseStream(stream_id, create_stream_callback); |
327 return; | 415 return; |
328 } | 416 } |
329 | 417 |
330 Send(new AudioMsg_NotifyStreamCreated( | 418 mojo::ScopedHandle socket_handle = |
331 entry->stream_id(), foreign_memory_handle, socket_descriptor, | 419 mojo::ScopedHandle(mojo::Handle(socket_descriptor_handle)); |
332 entry->shared_memory()->requested_size())); | 420 create_stream_callback.Run( |
| 421 stream_id, std::move(stream_ptr), |
| 422 std::move(shared_buffer_handle), std::move(socket_handle)); |
| 423 |
| 424 entry->get_create_stream_callback()->reset(); |
333 } | 425 } |
334 | 426 |
335 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, | 427 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, |
336 bool is_playing) { | 428 bool is_playing) { |
337 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 429 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
338 | 430 |
339 AudioEntry* const entry = LookupById(stream_id); | 431 AudioEntry* const entry = LookupById(stream_id); |
340 if (!entry) | 432 if (!entry) |
341 return; | 433 return; |
342 | 434 |
(...skipping 30 matching lines...) Expand all Loading... |
373 return controllers; | 465 return controllers; |
374 } | 466 } |
375 | 467 |
376 /////////////////////////////////////////////////////////////////////////////// | 468 /////////////////////////////////////////////////////////////////////////////// |
377 // IPC Messages handler | 469 // IPC Messages handler |
378 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { | 470 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { |
379 bool handled = true; | 471 bool handled = true; |
380 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) | 472 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) |
381 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization, | 473 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization, |
382 OnRequestDeviceAuthorization) | 474 OnRequestDeviceAuthorization) |
383 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) | |
384 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) | 475 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) |
385 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) | 476 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) |
386 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) | 477 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, CloseStream) |
387 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) | 478 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) |
388 IPC_MESSAGE_UNHANDLED(handled = false) | 479 IPC_MESSAGE_UNHANDLED(handled = false) |
389 IPC_END_MESSAGE_MAP() | 480 IPC_END_MESSAGE_MAP() |
390 | 481 |
391 return handled; | 482 return handled; |
392 } | 483 } |
393 | 484 |
394 void AudioRendererHost::OnRequestDeviceAuthorization( | 485 void AudioRendererHost::OnRequestDeviceAuthorization( |
395 int stream_id, | 486 int stream_id, |
396 int render_frame_id, | 487 int render_frame_id, |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 | 601 |
511 auth_data->second.first = true; | 602 auth_data->second.first = true; |
512 auth_data->second.second = device_info.unique_id; | 603 auth_data->second.second = device_info.unique_id; |
513 | 604 |
514 media::AudioParameters output_params = device_info.output_params; | 605 media::AudioParameters output_params = device_info.output_params; |
515 MaybeFixAudioParameters(&output_params); | 606 MaybeFixAudioParameters(&output_params); |
516 Send(new AudioMsg_NotifyDeviceAuthorized( | 607 Send(new AudioMsg_NotifyDeviceAuthorized( |
517 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); | 608 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); |
518 } | 609 } |
519 | 610 |
520 void AudioRendererHost::OnCreateStream(int stream_id, | 611 void AudioRendererHost::CreateStream( |
521 int render_frame_id, | 612 int stream_id, |
522 const media::AudioParameters& params) { | 613 int render_frame_id, |
| 614 const media::AudioParameters& params, |
| 615 const media::mojom::AudioOutput::CreateStreamCallback& |
| 616 create_stream_callback) { |
523 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 617 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
524 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" | 618 DVLOG(1) << "AudioRendererHost@" << this << "::CreateStream" |
525 << "(stream_id=" << stream_id << ")"; | 619 << "(stream_id=" << stream_id << ")"; |
526 | 620 |
527 const auto& auth_data = authorizations_.find(stream_id); | 621 const auto& auth_data = authorizations_.find(stream_id); |
528 | 622 |
529 // If no previous authorization requested, assume default device | 623 // If no previous authorization requested, assume default device |
530 if (auth_data == authorizations_.end()) { | 624 if (auth_data == authorizations_.end()) { |
531 DoCreateStream(stream_id, render_frame_id, params, std::string()); | 625 DoCreateStream(stream_id, render_frame_id, params, std::string(), |
| 626 create_stream_callback); |
532 return; | 627 return; |
533 } | 628 } |
534 | 629 |
535 CHECK(auth_data->second.first); | 630 CHECK(auth_data->second.first); |
536 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second); | 631 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second, |
| 632 create_stream_callback); |
537 authorizations_.erase(auth_data); | 633 authorizations_.erase(auth_data); |
538 } | 634 } |
539 | 635 |
540 void AudioRendererHost::DoCreateStream(int stream_id, | 636 void AudioRendererHost::DoCreateStream( |
541 int render_frame_id, | 637 int stream_id, |
542 const media::AudioParameters& params, | 638 int render_frame_id, |
543 const std::string& device_unique_id) { | 639 const media::AudioParameters& params, |
| 640 const std::string& device_unique_id, |
| 641 const media::mojom::AudioOutput::CreateStreamCallback& |
| 642 create_stream_callback) { |
544 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 643 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
545 | 644 |
546 // media::AudioParameters is validated in the deserializer. | 645 // media::AudioParameters is validated in the deserializer. |
547 if (LookupById(stream_id) != NULL) { | 646 if (LookupById(stream_id) != NULL) { |
548 SendErrorMessage(stream_id); | 647 SendErrorMessage(stream_id); |
549 return; | 648 return; |
550 } | 649 } |
551 | 650 |
552 // Create the shared memory and share with the renderer process. | 651 // Create the shared memory and share with the renderer process. |
553 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) + | 652 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) + |
554 AudioBus::CalculateMemorySize(params); | 653 AudioBus::CalculateMemorySize(params); |
555 std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); | 654 std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); |
556 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) { | 655 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) { |
557 SendErrorMessage(stream_id); | 656 SendErrorMessage(stream_id); |
558 return; | 657 return; |
559 } | 658 } |
560 | 659 |
561 std::unique_ptr<AudioSyncReader> reader( | 660 std::unique_ptr<AudioSyncReader> reader( |
562 new AudioSyncReader(shared_memory.get(), params)); | 661 new AudioSyncReader(shared_memory.get(), params)); |
563 if (!reader->Init()) { | 662 if (!reader->Init()) { |
564 SendErrorMessage(stream_id); | 663 SendErrorMessage(stream_id); |
565 return; | 664 return; |
566 } | 665 } |
567 | 666 |
568 MediaObserver* const media_observer = | 667 MediaObserver* const media_observer = |
569 GetContentClient()->browser()->GetMediaObserver(); | 668 GetContentClient()->browser()->GetMediaObserver(); |
570 if (media_observer) | 669 if (media_observer) |
571 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); | 670 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); |
572 | 671 |
573 std::unique_ptr<AudioEntry> entry( | 672 std::unique_ptr<AudioEntry> entry(new AudioEntry( |
574 new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id, | 673 this, stream_id, render_frame_id, params, device_unique_id, |
575 std::move(shared_memory), std::move(reader))); | 674 std::move(shared_memory), std::move(reader), create_stream_callback)); |
576 if (mirroring_manager_) { | 675 if (mirroring_manager_) { |
577 mirroring_manager_->AddDiverter( | 676 mirroring_manager_->AddDiverter( |
578 render_process_id_, entry->render_frame_id(), entry->controller()); | 677 render_process_id_, entry->render_frame_id(), entry->controller()); |
579 } | 678 } |
580 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 679 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
581 g_audio_streams_tracker.Get().IncreaseStreamCount(); | 680 g_audio_streams_tracker.Get().IncreaseStreamCount(); |
582 | 681 |
583 audio_log_->OnCreated(stream_id, params, device_unique_id); | 682 audio_log_->OnCreated(stream_id, params, device_unique_id); |
584 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( | 683 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( |
585 stream_id, render_process_id_, render_frame_id, audio_log_.get()); | 684 stream_id, render_process_id_, render_frame_id, audio_log_.get()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 return; | 727 return; |
629 entry->controller()->SetVolume(volume); | 728 entry->controller()->SetVolume(volume); |
630 audio_log_->OnSetVolume(stream_id, volume); | 729 audio_log_->OnSetVolume(stream_id, volume); |
631 } | 730 } |
632 | 731 |
633 void AudioRendererHost::SendErrorMessage(int stream_id) { | 732 void AudioRendererHost::SendErrorMessage(int stream_id) { |
634 Send(new AudioMsg_NotifyStreamStateChanged( | 733 Send(new AudioMsg_NotifyStreamStateChanged( |
635 stream_id, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)); | 734 stream_id, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)); |
636 } | 735 } |
637 | 736 |
638 void AudioRendererHost::OnCloseStream(int stream_id) { | 737 void AudioRendererHost::CloseStream(int stream_id) { |
639 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 738 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
640 authorizations_.erase(stream_id); | 739 authorizations_.erase(stream_id); |
641 | 740 |
642 // Prevent oustanding callbacks from attempting to close/delete the same | 741 // Prevent oustanding callbacks from attempting to close/delete the same |
643 // AudioEntry twice. | 742 // AudioEntry twice. |
644 AudioEntryMap::iterator i = audio_entries_.find(stream_id); | 743 AudioEntryMap::iterator i = audio_entries_.find(stream_id); |
645 if (i == audio_entries_.end()) | 744 if (i == audio_entries_.end()) |
646 return; | 745 return; |
647 std::unique_ptr<AudioEntry> entry(i->second); | 746 std::unique_ptr<AudioEntry> entry(i->second); |
648 audio_entries_.erase(i); | 747 audio_entries_.erase(i); |
(...skipping 26 matching lines...) Expand all Loading... |
675 | 774 |
676 // Make sure this isn't a stray callback executing after the stream has been | 775 // Make sure this isn't a stray callback executing after the stream has been |
677 // closed, so error notifications aren't sent after clients believe the stream | 776 // closed, so error notifications aren't sent after clients believe the stream |
678 // is closed. | 777 // is closed. |
679 if (!LookupById(stream_id)) | 778 if (!LookupById(stream_id)) |
680 return; | 779 return; |
681 | 780 |
682 SendErrorMessage(stream_id); | 781 SendErrorMessage(stream_id); |
683 | 782 |
684 audio_log_->OnError(stream_id); | 783 audio_log_->OnError(stream_id); |
685 OnCloseStream(stream_id); | 784 CloseStream(stream_id); |
| 785 } |
| 786 |
| 787 void AudioRendererHost::ReportErrorAndCloseStream( |
| 788 int stream_id, |
| 789 const media::mojom::AudioOutput::CreateStreamCallback& callback) { |
| 790 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 791 |
| 792 // Make sure this isn't a stray callback executing after the stream has been |
| 793 // closed, so error notifications aren't sent after clients believe the stream |
| 794 // is closed. |
| 795 if (!LookupById(stream_id)) |
| 796 return; |
| 797 |
| 798 mojo::ScopedSharedBufferHandle shared_buffer_handle = |
| 799 mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle()); |
| 800 |
| 801 mojo::ScopedHandle socket_handle = mojo::ScopedHandle(mojo::Handle()); |
| 802 |
| 803 callback.Run(stream_id, media::mojom::AudioOutputStreamPtr(), |
| 804 std::move(shared_buffer_handle), std::move(socket_handle)); |
| 805 |
| 806 audio_log_->OnError(stream_id); |
| 807 CloseStream(stream_id); |
686 } | 808 } |
687 | 809 |
688 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { | 810 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
689 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 811 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
690 | 812 |
691 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); | 813 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); |
692 return i != audio_entries_.end() ? i->second : NULL; | 814 return i != audio_entries_.end() ? i->second : NULL; |
693 } | 815 } |
694 | 816 |
695 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, | 817 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 for (AudioEntryMap::const_iterator it = audio_entries_.begin(); | 852 for (AudioEntryMap::const_iterator it = audio_entries_.begin(); |
731 it != audio_entries_.end(); | 853 it != audio_entries_.end(); |
732 ++it) { | 854 ++it) { |
733 AudioEntry* entry = it->second; | 855 AudioEntry* entry = it->second; |
734 if (entry->render_frame_id() == render_frame_id && entry->playing()) | 856 if (entry->render_frame_id() == render_frame_id && entry->playing()) |
735 return true; | 857 return true; |
736 } | 858 } |
737 return false; | 859 return false; |
738 } | 860 } |
739 | 861 |
| 862 AudioOutputImpl* AudioRendererHost::get_audio_output_impl( |
| 863 int render_frame_id) const { |
| 864 auto result = audio_output_impls_.find(render_frame_id); |
| 865 if (result != audio_output_impls_.end()) |
| 866 return result->second; |
| 867 else |
| 868 return NULL; |
| 869 } |
| 870 |
| 871 void AudioRendererHost::set_audio_output_impl( |
| 872 int render_frame_id, |
| 873 AudioOutputImpl* audio_output_impl) { |
| 874 audio_output_impls_.insert( |
| 875 std::make_pair(render_frame_id, audio_output_impl)); |
| 876 } |
| 877 |
740 void AudioRendererHost::CheckOutputDeviceAccess( | 878 void AudioRendererHost::CheckOutputDeviceAccess( |
741 int render_frame_id, | 879 int render_frame_id, |
742 const std::string& device_id, | 880 const std::string& device_id, |
743 const url::Origin& security_origin, | 881 const url::Origin& security_origin, |
744 const OutputDeviceAccessCB& callback) { | 882 const OutputDeviceAccessCB& callback) { |
745 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 883 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
746 | 884 |
747 // Check security origin if nondefault device is requested. | 885 // Check security origin if nondefault device is requested. |
748 // Ignore check for default device, which is always authorized. | 886 // Ignore check for default device, which is always authorized. |
749 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) && | 887 if (!media::AudioDeviceDescription::IsDefaultDevice(device_id) && |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 callback.Run(false, device_info); | 946 callback.Run(false, device_info); |
809 } | 947 } |
810 | 948 |
811 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { | 949 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { |
812 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 950 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
813 const auto& i = authorizations_.find(stream_id); | 951 const auto& i = authorizations_.find(stream_id); |
814 return i != authorizations_.end(); | 952 return i != authorizations_.end(); |
815 } | 953 } |
816 | 954 |
817 } // namespace content | 955 } // namespace content |
OLD | NEW |