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" |
19 #include "content/browser/child_process_security_policy_impl.h" | 22 #include "content/browser/child_process_security_policy_impl.h" |
| 23 #include "content/browser/media/audio_output_impl.h" |
20 #include "content/browser/media/audio_stream_monitor.h" | 24 #include "content/browser/media/audio_stream_monitor.h" |
21 #include "content/browser/media/capture/audio_mirroring_manager.h" | 25 #include "content/browser/media/capture/audio_mirroring_manager.h" |
22 #include "content/browser/media/media_internals.h" | 26 #include "content/browser/media/media_internals.h" |
23 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 27 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
24 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 28 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
25 #include "content/browser/renderer_host/media/media_stream_manager.h" | 29 #include "content/browser/renderer_host/media/media_stream_manager.h" |
26 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" | 30 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" |
27 #include "content/browser/renderer_host/render_widget_host_impl.h" | 31 #include "content/browser/renderer_host/render_widget_host_impl.h" |
28 #include "content/common/media/audio_messages.h" | 32 #include "content/common/media/audio_messages.h" |
29 #include "content/public/browser/content_browser_client.h" | 33 #include "content/public/browser/content_browser_client.h" |
30 #include "content/public/browser/media_device_id.h" | 34 #include "content/public/browser/media_device_id.h" |
31 #include "content/public/browser/media_observer.h" | 35 #include "content/public/browser/media_observer.h" |
32 #include "content/public/browser/render_frame_host.h" | 36 #include "content/public/browser/render_frame_host.h" |
33 #include "content/public/common/content_switches.h" | 37 #include "content/public/common/content_switches.h" |
34 #include "media/audio/audio_device_name.h" | 38 #include "media/audio/audio_device_name.h" |
35 #include "media/audio/audio_manager_base.h" | 39 #include "media/audio/audio_manager_base.h" |
36 #include "media/audio/audio_streams_tracker.h" | 40 #include "media/audio/audio_streams_tracker.h" |
37 #include "media/base/audio_bus.h" | 41 #include "media/base/audio_bus.h" |
38 #include "media/base/limits.h" | 42 #include "media/base/limits.h" |
| 43 #include "mojo/edk/embedder/embedder.h" |
| 44 #include "mojo/public/cpp/system/handle.h" |
39 | 45 |
40 using media::AudioBus; | 46 using media::AudioBus; |
41 using media::AudioManager; | 47 using media::AudioManager; |
42 | 48 |
43 namespace content { | 49 namespace content { |
44 | 50 |
45 namespace { | 51 namespace { |
46 | 52 |
47 // Tracks the maximum number of simultaneous output streams browser-wide. | 53 // Tracks the maximum number of simultaneous output streams browser-wide. |
48 // Accessed on IO thread. | 54 // Accessed on IO thread. |
49 base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker = | 55 base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker = |
50 LAZY_INSTANCE_INITIALIZER; | 56 LAZY_INSTANCE_INITIALIZER; |
51 | 57 |
52 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData( | 58 std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData( |
53 int stream_id, | 59 int stream_id, |
54 bool authorized, | 60 bool authorized, |
55 const std::string& device_unique_id) { | 61 const std::string& device_unique_id) { |
56 return std::make_pair(stream_id, | 62 return std::make_pair(stream_id, |
57 std::make_pair(authorized, device_unique_id)); | 63 std::make_pair(authorized, device_unique_id)); |
58 } | 64 } |
59 | 65 |
60 GURL ConvertToGURL(const url::Origin& origin) { | 66 GURL ConvertToGURL(const url::Origin& origin) { |
61 return origin.unique() ? GURL() : GURL(origin.Serialize()); | 67 return origin.unique() ? GURL() : GURL(origin.Serialize()); |
62 } | 68 } |
63 | 69 |
| 70 base::SyncSocket::TransitDescriptor DuplicateSocket( |
| 71 base::SyncSocket::TransitDescriptor socket_descriptor) { |
| 72 base::SyncSocket::TransitDescriptor socket_descriptor_dup; |
| 73 |
| 74 #if defined(OS_WIN) |
| 75 socket_descriptor_dup = 0; |
| 76 if(!::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle |
| 77 socket_descriptor, |
| 78 GetCurrentProcess(), // hTargetProcessHandle |
| 79 &socket_descriptor_dup, |
| 80 0, // dwDesiredAccess ignored due to SAME_ACCESS |
| 81 FALSE, // !bInheritHandle |
| 82 DUPLICATE_SAME_ACCESS)){ |
| 83 LOG(ERROR) << "Unable to duplicate socket handle."; |
| 84 } |
| 85 |
| 86 #else |
| 87 socket_descriptor_dup.fd = dup(socket_descriptor.fd); |
| 88 #endif |
| 89 return socket_descriptor_dup; |
| 90 } |
| 91 |
64 bool IsValidDeviceId(const std::string& device_id) { | 92 bool IsValidDeviceId(const std::string& device_id) { |
65 static const std::string::size_type kValidLength = 64; | 93 static const std::string::size_type kValidLength = 64; |
66 | 94 |
67 if (device_id.empty() || | 95 if (device_id.empty() || |
68 device_id == media::AudioManagerBase::kDefaultDeviceId || | 96 device_id == media::AudioManagerBase::kDefaultDeviceId || |
69 device_id == media::AudioManagerBase::kCommunicationsDeviceId) { | 97 device_id == media::AudioManagerBase::kCommunicationsDeviceId) { |
70 return true; | 98 return true; |
71 } | 99 } |
72 | 100 |
73 if (device_id.length() != kValidLength) | 101 if (device_id.length() != kValidLength) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
119 | 147 |
120 class AudioRendererHost::AudioEntry | 148 class AudioRendererHost::AudioEntry |
121 : public media::AudioOutputController::EventHandler { | 149 : public media::AudioOutputController::EventHandler { |
122 public: | 150 public: |
123 AudioEntry(AudioRendererHost* host, | 151 AudioEntry(AudioRendererHost* host, |
124 int stream_id, | 152 int stream_id, |
125 int render_frame_id, | 153 int render_frame_id, |
126 const media::AudioParameters& params, | 154 const media::AudioParameters& params, |
127 const std::string& output_device_id, | 155 const std::string& output_device_id, |
128 std::unique_ptr<base::SharedMemory> shared_memory, | 156 std::unique_ptr<base::SharedMemory> shared_memory, |
129 std::unique_ptr<media::AudioOutputController::SyncReader> reader); | 157 std::unique_ptr<media::AudioOutputController::SyncReader> reader, |
| 158 const media::interfaces::AudioOutput::CreateStreamCallback& callbac
k); |
130 ~AudioEntry() override; | 159 ~AudioEntry() override; |
131 | 160 |
132 int stream_id() const { | 161 int stream_id() const { |
133 return stream_id_; | 162 return stream_id_; |
134 } | 163 } |
135 | 164 |
136 int render_frame_id() const { return render_frame_id_; } | 165 int render_frame_id() const { return render_frame_id_; } |
137 | 166 |
138 media::AudioOutputController* controller() const { return controller_.get(); } | 167 media::AudioOutputController* controller() const { return controller_.get(); } |
139 | 168 |
140 base::SharedMemory* shared_memory() { | 169 base::SharedMemory* shared_memory() { |
141 return shared_memory_.get(); | 170 return shared_memory_.get(); |
142 } | 171 } |
143 | 172 |
144 media::AudioOutputController::SyncReader* reader() const { | 173 media::AudioOutputController::SyncReader* reader() const { |
145 return reader_.get(); | 174 return reader_.get(); |
146 } | 175 } |
147 | 176 |
148 bool playing() const { return playing_; } | 177 bool playing() const { return playing_; } |
149 void set_playing(bool playing) { playing_ = playing; } | 178 void set_playing(bool playing) { playing_ = playing; } |
150 | 179 |
151 private: | 180 private: |
152 // media::AudioOutputController::EventHandler implementation. | 181 // media::AudioOutputController::EventHandler implementation. |
153 void OnCreated() override; | 182 void OnCreated( |
| 183 const media::interfaces::AudioOutput::CreateStreamCallback& callback) over
ride; |
154 void OnPlaying() override; | 184 void OnPlaying() override; |
155 void OnPaused() override; | 185 void OnPaused() override; |
156 void OnError() override; | 186 void OnError() override; |
157 | 187 |
158 AudioRendererHost* const host_; | 188 AudioRendererHost* const host_; |
159 const int stream_id_; | 189 const int stream_id_; |
160 | 190 |
161 // The routing ID of the source RenderFrame. | 191 // The routing ID of the source RenderFrame. |
162 const int render_frame_id_; | 192 const int render_frame_id_; |
163 | 193 |
164 // Shared memory for transmission of the audio data. Used by |reader_|. | 194 // Shared memory for transmission of the audio data. Used by |reader_|. |
165 const std::unique_ptr<base::SharedMemory> shared_memory_; | 195 const std::unique_ptr<base::SharedMemory> shared_memory_; |
166 | 196 |
167 // The synchronous reader to be used by |controller_|. | 197 // The synchronous reader to be used by |controller_|. |
168 const std::unique_ptr<media::AudioOutputController::SyncReader> reader_; | 198 const std::unique_ptr<media::AudioOutputController::SyncReader> reader_; |
169 | 199 |
170 // The AudioOutputController that manages the audio stream. | 200 // The AudioOutputController that manages the audio stream. |
171 const scoped_refptr<media::AudioOutputController> controller_; | 201 const scoped_refptr<media::AudioOutputController> controller_; |
172 | 202 |
173 bool playing_; | 203 bool playing_; |
174 }; | 204 }; |
175 | 205 |
176 AudioRendererHost::AudioEntry::AudioEntry( | 206 AudioRendererHost::AudioEntry::AudioEntry( |
177 AudioRendererHost* host, | 207 AudioRendererHost* host, |
178 int stream_id, | 208 int stream_id, |
179 int render_frame_id, | 209 int render_frame_id, |
180 const media::AudioParameters& params, | 210 const media::AudioParameters& params, |
181 const std::string& output_device_id, | 211 const std::string& output_device_id, |
182 std::unique_ptr<base::SharedMemory> shared_memory, | 212 std::unique_ptr<base::SharedMemory> shared_memory, |
183 std::unique_ptr<media::AudioOutputController::SyncReader> reader) | 213 std::unique_ptr<media::AudioOutputController::SyncReader> reader, |
| 214 const media::interfaces::AudioOutput::CreateStreamCallback& callback) |
184 : host_(host), | 215 : host_(host), |
185 stream_id_(stream_id), | 216 stream_id_(stream_id), |
186 render_frame_id_(render_frame_id), | 217 render_frame_id_(render_frame_id), |
187 shared_memory_(std::move(shared_memory)), | 218 shared_memory_(std::move(shared_memory)), |
188 reader_(std::move(reader)), | 219 reader_(std::move(reader)), |
189 controller_(media::AudioOutputController::Create(host->audio_manager_, | 220 controller_(media::AudioOutputController::Create(host->audio_manager_, |
190 this, | 221 this, |
191 params, | 222 params, |
192 output_device_id, | 223 output_device_id, |
193 reader_.get())), | 224 reader_.get(), |
| 225 callback)), |
194 playing_(false) { | 226 playing_(false) { |
195 DCHECK(controller_.get()); | 227 DCHECK(controller_.get()); |
196 } | 228 } |
197 | 229 |
198 AudioRendererHost::AudioEntry::~AudioEntry() {} | 230 AudioRendererHost::AudioEntry::~AudioEntry() {} |
199 | 231 |
200 /////////////////////////////////////////////////////////////////////////////// | 232 /////////////////////////////////////////////////////////////////////////////// |
201 // AudioRendererHost implementations. | 233 // AudioRendererHost implementations. |
202 | 234 |
203 AudioRendererHost::AudioRendererHost( | 235 AudioRendererHost::AudioRendererHost( |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 } | 287 } |
256 | 288 |
257 // Remove any authorizations for streams that were not yet created | 289 // Remove any authorizations for streams that were not yet created |
258 authorizations_.clear(); | 290 authorizations_.clear(); |
259 } | 291 } |
260 | 292 |
261 void AudioRendererHost::OnDestruct() const { | 293 void AudioRendererHost::OnDestruct() const { |
262 BrowserThread::DeleteOnIOThread::Destruct(this); | 294 BrowserThread::DeleteOnIOThread::Destruct(this); |
263 } | 295 } |
264 | 296 |
265 void AudioRendererHost::AudioEntry::OnCreated() { | 297 void AudioRendererHost::AudioEntry::OnCreated( |
266 BrowserThread::PostTask( | 298 const media::interfaces::AudioOutput::CreateStreamCallback& callback) { |
267 BrowserThread::IO, | 299 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
268 FROM_HERE, | 300 base::Bind(&AudioRendererHost::DoCompleteCreation, |
269 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_)); | 301 host_, stream_id_, callback)); |
270 } | 302 } |
271 | 303 |
272 void AudioRendererHost::AudioEntry::OnPlaying() { | 304 void AudioRendererHost::AudioEntry::OnPlaying() { |
273 BrowserThread::PostTask( | 305 BrowserThread::PostTask( |
274 BrowserThread::IO, | 306 BrowserThread::IO, |
275 FROM_HERE, | 307 FROM_HERE, |
276 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, | 308 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, |
277 host_, | 309 host_, |
278 stream_id_, | 310 stream_id_, |
279 true)); | 311 true)); |
280 } | 312 } |
281 | 313 |
282 void AudioRendererHost::AudioEntry::OnPaused() { | 314 void AudioRendererHost::AudioEntry::OnPaused() { |
283 BrowserThread::PostTask( | 315 BrowserThread::PostTask( |
284 BrowserThread::IO, | 316 BrowserThread::IO, |
285 FROM_HERE, | 317 FROM_HERE, |
286 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, | 318 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, |
287 host_, | 319 host_, |
288 stream_id_, | 320 stream_id_, |
289 false)); | 321 false)); |
290 } | 322 } |
291 | 323 |
292 void AudioRendererHost::AudioEntry::OnError() { | 324 void AudioRendererHost::AudioEntry::OnError() { |
293 BrowserThread::PostTask( | 325 BrowserThread::PostTask( |
294 BrowserThread::IO, | 326 BrowserThread::IO, |
295 FROM_HERE, | 327 FROM_HERE, |
296 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); | 328 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); |
297 } | 329 } |
298 | 330 |
299 void AudioRendererHost::DoCompleteCreation(int stream_id) { | 331 void AudioRendererHost::DoCompleteCreation( |
| 332 int stream_id, |
| 333 const media::interfaces::AudioOutput::CreateStreamCallback& callback) { |
300 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 334 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
301 | 335 |
302 if (!PeerHandle()) { | 336 if (!PeerHandle()) { |
303 DLOG(WARNING) << "Renderer process handle is invalid."; | 337 DLOG(WARNING) << "Renderer process handle is invalid."; |
304 ReportErrorAndClose(stream_id); | 338 ReportErrorAndCloseStream(stream_id, callback); |
305 return; | 339 return; |
306 } | 340 } |
307 | 341 |
308 AudioEntry* const entry = LookupById(stream_id); | 342 AudioEntry* const entry = LookupById(stream_id); |
309 if (!entry) { | 343 if (!entry) { |
310 ReportErrorAndClose(stream_id); | 344 ReportErrorAndCloseStream(stream_id, callback); |
311 return; | 345 return; |
312 } | 346 } |
313 | 347 |
314 // Once the audio stream is created then complete the creation process by | 348 std::unique_ptr<media::interfaces::AudioOutputStreamPtr> stream_ptr( |
315 // mapping shared memory and sharing with the renderer process. | 349 audio_output_impl_->StreamFactory(stream_id, this)); |
316 base::SharedMemoryHandle foreign_memory_handle; | 350 |
317 if (!entry->shared_memory()->ShareToProcess(PeerHandle(), | 351 base::SharedMemoryHandle shared_memory_handle = |
318 &foreign_memory_handle)) { | 352 base::SharedMemory::DuplicateHandle(entry->shared_memory()->handle()); |
319 // If we failed to map and share the shared memory then close the audio | 353 |
320 // stream and send an error message. | 354 MojoHandle mojo_foreign_memory_handle; |
321 ReportErrorAndClose(entry->stream_id()); | 355 |
| 356 MojoResult shared_buffer_result = mojo::edk::CreateSharedBufferWrapper( |
| 357 shared_memory_handle, entry->shared_memory()->requested_size(), false, |
| 358 &mojo_foreign_memory_handle); |
| 359 |
| 360 if (shared_buffer_result != MOJO_RESULT_OK) { |
| 361 DLOG(WARNING) << "Failed to wrap transit descriptor. Closing: " |
| 362 << shared_buffer_result; |
| 363 ReportErrorAndCloseStream(entry->stream_id(), callback); |
322 return; | 364 return; |
323 } | 365 } |
324 | 366 |
325 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); | 367 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); |
326 | 368 |
327 base::SyncSocket::TransitDescriptor socket_descriptor; | 369 base::SyncSocket::TransitDescriptor socket_descriptor; |
328 | 370 |
329 // If we failed to prepare the sync socket for the renderer then we fail | 371 // If we failed to prepare the sync socket for the renderer then we fail |
330 // the construction of audio stream. | 372 // the construction of audio stream. |
331 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { | 373 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { |
332 ReportErrorAndClose(entry->stream_id()); | 374 ReportErrorAndCloseStream(entry->stream_id(), callback); |
| 375 return; |
| 376 } |
| 377 mojo::ScopedSharedBufferHandle shared_buffer_handle = |
| 378 mojo::ScopedSharedBufferHandle( |
| 379 mojo::SharedBufferHandle(mojo_foreign_memory_handle)); |
| 380 |
| 381 MojoHandle socket_descriptor_handle; |
| 382 MojoResult platform_handle_result; |
| 383 |
| 384 // The socket handle is going to be closed when |mojo_application_host_| is |
| 385 // reset. AudioOutputIPCDelegate is going to need to close the socket handle |
| 386 // too when the steam it controls is closed. This is going to cause an issue |
| 387 // because both of them are going to close the same socket handle. |
| 388 // This is why a duplicate of the socket handler is going to be created, |
| 389 // stored in |socket_descriptor_dup| and sent through Mojo to the renderer so |
| 390 // it can be used by AudioOutputIPCDelegate. |
| 391 |
| 392 base::SyncSocket::TransitDescriptor socket_descriptor_dup = |
| 393 DuplicateSocket(socket_descriptor); |
| 394 #if defined(OS_WIN) |
| 395 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( |
| 396 mojo::edk::ScopedPlatformHandle( |
| 397 mojo::edk::PlatformHandle(socket_descriptor_dup), |
| 398 &socket_descriptor_handle); |
| 399 #else |
| 400 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( |
| 401 mojo::edk::ScopedPlatformHandle( |
| 402 mojo::edk::PlatformHandle(socket_descriptor_dup.fd)), |
| 403 &socket_descriptor_handle); |
| 404 #endif |
| 405 |
| 406 if (platform_handle_result != MOJO_RESULT_OK) { |
| 407 DLOG(WARNING) << "Failed to wrap platform handle. Closing: " |
| 408 << platform_handle_result; |
| 409 ReportErrorAndCloseStream(stream_id, callback); |
333 return; | 410 return; |
334 } | 411 } |
335 | 412 |
336 Send(new AudioMsg_NotifyStreamCreated( | 413 mojo::ScopedHandle socket_handle = |
337 entry->stream_id(), foreign_memory_handle, socket_descriptor, | 414 mojo::ScopedHandle(mojo::Handle(socket_descriptor_handle)); |
338 entry->shared_memory()->requested_size())); | 415 callback.Run(stream_id, std::move(*stream_ptr), |
| 416 std::move(shared_buffer_handle), std::move(socket_handle)); |
| 417 |
339 } | 418 } |
340 | 419 |
341 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, | 420 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, |
342 bool is_playing) { | 421 bool is_playing) { |
343 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 422 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
344 | 423 |
345 AudioEntry* const entry = LookupById(stream_id); | 424 AudioEntry* const entry = LookupById(stream_id); |
346 if (!entry) | 425 if (!entry) |
347 return; | 426 return; |
348 | 427 |
(...skipping 30 matching lines...) Expand all Loading... |
379 return controllers; | 458 return controllers; |
380 } | 459 } |
381 | 460 |
382 /////////////////////////////////////////////////////////////////////////////// | 461 /////////////////////////////////////////////////////////////////////////////// |
383 // IPC Messages handler | 462 // IPC Messages handler |
384 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { | 463 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { |
385 bool handled = true; | 464 bool handled = true; |
386 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) | 465 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) |
387 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization, | 466 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization, |
388 OnRequestDeviceAuthorization) | 467 OnRequestDeviceAuthorization) |
389 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) | |
390 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) | 468 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) |
391 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) | 469 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) |
392 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) | 470 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) |
393 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) | 471 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) |
394 IPC_MESSAGE_UNHANDLED(handled = false) | 472 IPC_MESSAGE_UNHANDLED(handled = false) |
395 IPC_END_MESSAGE_MAP() | 473 IPC_END_MESSAGE_MAP() |
396 | 474 |
397 return handled; | 475 return handled; |
398 } | 476 } |
399 | 477 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 | 596 |
519 auth_data->second.first = true; | 597 auth_data->second.first = true; |
520 auth_data->second.second = device_info.unique_id; | 598 auth_data->second.second = device_info.unique_id; |
521 | 599 |
522 media::AudioParameters output_params = device_info.output_params; | 600 media::AudioParameters output_params = device_info.output_params; |
523 MaybeFixAudioParameters(&output_params); | 601 MaybeFixAudioParameters(&output_params); |
524 Send(new AudioMsg_NotifyDeviceAuthorized( | 602 Send(new AudioMsg_NotifyDeviceAuthorized( |
525 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); | 603 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); |
526 } | 604 } |
527 | 605 |
528 void AudioRendererHost::OnCreateStream(int stream_id, | 606 void AudioRendererHost::CreateStream( |
529 int render_frame_id, | 607 int stream_id, |
530 const media::AudioParameters& params) { | 608 int render_frame_id, |
| 609 const media::AudioParameters& params, |
| 610 const media::interfaces::AudioOutput::CreateStreamCallback& callback) { |
531 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 611 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
532 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" | 612 DVLOG(1) << "AudioRendererHost@" << this << "::CreateStream" |
533 << "(stream_id=" << stream_id << ")"; | 613 << "(stream_id=" << stream_id << ")"; |
534 | 614 |
535 const auto& auth_data = authorizations_.find(stream_id); | 615 const auto& auth_data = authorizations_.find(stream_id); |
536 | 616 |
537 // If no previous authorization requested, assume default device | 617 // If no previous authorization requested, assume default device |
538 if (auth_data == authorizations_.end()) { | 618 if (auth_data == authorizations_.end()) { |
539 DoCreateStream(stream_id, render_frame_id, params, std::string()); | 619 DoCreateStream(stream_id, render_frame_id, params, std::string(), callback); |
540 return; | 620 return; |
541 } | 621 } |
542 | 622 |
543 CHECK(auth_data->second.first); | 623 CHECK(auth_data->second.first); |
544 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second); | 624 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second, |
| 625 callback); |
545 authorizations_.erase(auth_data); | 626 authorizations_.erase(auth_data); |
546 } | 627 } |
547 | 628 |
548 void AudioRendererHost::DoCreateStream(int stream_id, | 629 void AudioRendererHost::DoCreateStream( |
549 int render_frame_id, | 630 int stream_id, |
550 const media::AudioParameters& params, | 631 int render_frame_id, |
551 const std::string& device_unique_id) { | 632 const media::AudioParameters& params, |
| 633 const std::string& device_unique_id, |
| 634 const media::interfaces::AudioOutput::CreateStreamCallback& callback) { |
552 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 635 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
553 | 636 |
554 // media::AudioParameters is validated in the deserializer. | 637 // media::AudioParameters is validated in the deserializer. |
555 if (LookupById(stream_id) != NULL) { | 638 if (LookupById(stream_id) != NULL) { |
556 SendErrorMessage(stream_id); | 639 SendErrorMessage(stream_id); |
557 return; | 640 return; |
558 } | 641 } |
559 | 642 |
560 // Create the shared memory and share with the renderer process. | 643 // Create the shared memory and share with the renderer process. |
561 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) + | 644 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) + |
(...skipping 11 matching lines...) Expand all Loading... |
573 return; | 656 return; |
574 } | 657 } |
575 | 658 |
576 MediaObserver* const media_observer = | 659 MediaObserver* const media_observer = |
577 GetContentClient()->browser()->GetMediaObserver(); | 660 GetContentClient()->browser()->GetMediaObserver(); |
578 if (media_observer) | 661 if (media_observer) |
579 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); | 662 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); |
580 | 663 |
581 std::unique_ptr<AudioEntry> entry( | 664 std::unique_ptr<AudioEntry> entry( |
582 new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id, | 665 new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id, |
583 std::move(shared_memory), std::move(reader))); | 666 std::move(shared_memory), std::move(reader), callback)); |
584 if (mirroring_manager_) { | 667 if (mirroring_manager_) { |
585 mirroring_manager_->AddDiverter( | 668 mirroring_manager_->AddDiverter( |
586 render_process_id_, entry->render_frame_id(), entry->controller()); | 669 render_process_id_, entry->render_frame_id(), entry->controller()); |
587 } | 670 } |
588 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 671 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
589 g_audio_streams_tracker.Get().IncreaseStreamCount(); | 672 g_audio_streams_tracker.Get().IncreaseStreamCount(); |
590 | 673 |
591 audio_log_->OnCreated(stream_id, params, device_unique_id); | 674 audio_log_->OnCreated(stream_id, params, device_unique_id); |
592 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( | 675 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( |
593 stream_id, render_process_id_, render_frame_id, audio_log_.get()); | 676 stream_id, render_process_id_, render_frame_id, audio_log_.get()); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 // is closed. | 769 // is closed. |
687 if (!LookupById(stream_id)) | 770 if (!LookupById(stream_id)) |
688 return; | 771 return; |
689 | 772 |
690 SendErrorMessage(stream_id); | 773 SendErrorMessage(stream_id); |
691 | 774 |
692 audio_log_->OnError(stream_id); | 775 audio_log_->OnError(stream_id); |
693 OnCloseStream(stream_id); | 776 OnCloseStream(stream_id); |
694 } | 777 } |
695 | 778 |
| 779 void AudioRendererHost::ReportErrorAndCloseStream( |
| 780 int stream_id, |
| 781 const media::interfaces::AudioOutput::CreateStreamCallback& callback) { |
| 782 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 783 |
| 784 // Make sure this isn't a stray callback executing after the stream has been |
| 785 // closed, so error notifications aren't sent after clients believe the stream |
| 786 // is closed. |
| 787 if (!LookupById(stream_id)) |
| 788 return; |
| 789 mojo::ScopedSharedBufferHandle shared_buffer_handle = |
| 790 mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle()); |
| 791 |
| 792 mojo::ScopedHandle socket_handle = mojo::ScopedHandle(mojo::Handle()); |
| 793 |
| 794 callback.Run(stream_id, media::interfaces::AudioOutputStreamPtr(), |
| 795 std::move(shared_buffer_handle), std::move(socket_handle)); |
| 796 |
| 797 audio_log_->OnError(stream_id); |
| 798 OnCloseStream(stream_id); |
| 799 } |
| 800 |
696 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { | 801 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
697 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 802 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
698 | 803 |
699 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); | 804 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); |
700 return i != audio_entries_.end() ? i->second : NULL; | 805 return i != audio_entries_.end() ? i->second : NULL; |
701 } | 806 } |
702 | 807 |
703 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, | 808 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, |
704 bool is_playing) { | 809 bool is_playing) { |
705 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 810 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 callback.Run(false, device_info); | 920 callback.Run(false, device_info); |
816 } | 921 } |
817 | 922 |
818 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { | 923 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { |
819 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 924 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
820 const auto& i = authorizations_.find(stream_id); | 925 const auto& i = authorizations_.find(stream_id); |
821 return i != authorizations_.end(); | 926 return i != authorizations_.end(); |
822 } | 927 } |
823 | 928 |
824 } // namespace content | 929 } // namespace content |
OLD | NEW |