| 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" | |
| 15 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
| 16 #include "base/process/process.h" | 18 #include "base/process/process.h" |
| 17 #include "content/browser/bad_message.h" | 19 #include "content/browser/bad_message.h" |
| 18 #include "content/browser/browser_main_loop.h" | 20 #include "content/browser/browser_main_loop.h" |
| 19 #include "content/browser/child_process_security_policy_impl.h" | 21 #include "content/browser/child_process_security_policy_impl.h" |
| 22 #include "content/browser/media/audio_output_impl.h" |
| 20 #include "content/browser/media/audio_stream_monitor.h" | 23 #include "content/browser/media/audio_stream_monitor.h" |
| 21 #include "content/browser/media/capture/audio_mirroring_manager.h" | 24 #include "content/browser/media/capture/audio_mirroring_manager.h" |
| 22 #include "content/browser/media/media_internals.h" | 25 #include "content/browser/media/media_internals.h" |
| 23 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 26 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| 24 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 27 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
| 25 #include "content/browser/renderer_host/media/media_stream_manager.h" | 28 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 26 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" | 29 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" |
| 27 #include "content/browser/renderer_host/render_widget_host_impl.h" | 30 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 28 #include "content/common/media/audio_messages.h" | 31 #include "content/common/media/audio_messages.h" |
| 29 #include "content/public/browser/content_browser_client.h" | 32 #include "content/public/browser/content_browser_client.h" |
| 30 #include "content/public/browser/media_device_id.h" | 33 #include "content/public/browser/media_device_id.h" |
| 31 #include "content/public/browser/media_observer.h" | 34 #include "content/public/browser/media_observer.h" |
| 32 #include "content/public/browser/render_frame_host.h" | 35 #include "content/public/browser/render_frame_host.h" |
| 33 #include "content/public/common/content_switches.h" | 36 #include "content/public/common/content_switches.h" |
| 34 #include "media/audio/audio_device_name.h" | 37 #include "media/audio/audio_device_name.h" |
| 35 #include "media/audio/audio_manager_base.h" | 38 #include "media/audio/audio_manager_base.h" |
| 36 #include "media/audio/audio_streams_tracker.h" | 39 #include "media/audio/audio_streams_tracker.h" |
| 37 #include "media/base/audio_bus.h" | 40 #include "media/base/audio_bus.h" |
| 38 #include "media/base/limits.h" | 41 #include "media/base/limits.h" |
| 42 #include "mojo/edk/embedder/embedder.h" |
| 43 #include "mojo/public/cpp/system/handle.h" |
| 39 | 44 |
| 40 using media::AudioBus; | 45 using media::AudioBus; |
| 41 using media::AudioManager; | 46 using media::AudioManager; |
| 42 | 47 |
| 43 namespace content { | 48 namespace content { |
| 44 | 49 |
| 45 namespace { | 50 namespace { |
| 46 | 51 |
| 47 // Tracks the maximum number of simultaneous output streams browser-wide. | 52 // Tracks the maximum number of simultaneous output streams browser-wide. |
| 48 // Accessed on IO thread. | 53 // Accessed on IO thread. |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 params->set_channels_for_discrete(media::limits::kMaxChannels); | 115 params->set_channels_for_discrete(media::limits::kMaxChannels); |
| 111 | 116 |
| 112 // If hardware parameters are still invalid, use dummy parameters with | 117 // If hardware parameters are still invalid, use dummy parameters with |
| 113 // fake audio path and let the client handle the error. | 118 // fake audio path and let the client handle the error. |
| 114 if (!params->IsValid()) | 119 if (!params->IsValid()) |
| 115 *params = media::AudioParameters::UnavailableDeviceParams(); | 120 *params = media::AudioParameters::UnavailableDeviceParams(); |
| 116 } | 121 } |
| 117 | 122 |
| 118 } // namespace | 123 } // namespace |
| 119 | 124 |
| 120 class AudioRendererHost::AudioEntry | |
| 121 : public media::AudioOutputController::EventHandler { | |
| 122 public: | |
| 123 AudioEntry(AudioRendererHost* host, | |
| 124 int stream_id, | |
| 125 int render_frame_id, | |
| 126 const media::AudioParameters& params, | |
| 127 const std::string& output_device_id, | |
| 128 std::unique_ptr<base::SharedMemory> shared_memory, | |
| 129 std::unique_ptr<media::AudioOutputController::SyncReader> reader); | |
| 130 ~AudioEntry() override; | |
| 131 | |
| 132 int stream_id() const { | |
| 133 return stream_id_; | |
| 134 } | |
| 135 | |
| 136 int render_frame_id() const { return render_frame_id_; } | |
| 137 | |
| 138 media::AudioOutputController* controller() const { return controller_.get(); } | |
| 139 | |
| 140 base::SharedMemory* shared_memory() { | |
| 141 return shared_memory_.get(); | |
| 142 } | |
| 143 | |
| 144 media::AudioOutputController::SyncReader* reader() const { | |
| 145 return reader_.get(); | |
| 146 } | |
| 147 | |
| 148 bool playing() const { return playing_; } | |
| 149 void set_playing(bool playing) { playing_ = playing; } | |
| 150 | |
| 151 private: | |
| 152 // media::AudioOutputController::EventHandler implementation. | |
| 153 void OnCreated() override; | |
| 154 void OnPlaying() override; | |
| 155 void OnPaused() override; | |
| 156 void OnError() override; | |
| 157 | |
| 158 AudioRendererHost* const host_; | |
| 159 const int stream_id_; | |
| 160 | |
| 161 // The routing ID of the source RenderFrame. | |
| 162 const int render_frame_id_; | |
| 163 | |
| 164 // Shared memory for transmission of the audio data. Used by |reader_|. | |
| 165 const std::unique_ptr<base::SharedMemory> shared_memory_; | |
| 166 | |
| 167 // The synchronous reader to be used by |controller_|. | |
| 168 const std::unique_ptr<media::AudioOutputController::SyncReader> reader_; | |
| 169 | |
| 170 // The AudioOutputController that manages the audio stream. | |
| 171 const scoped_refptr<media::AudioOutputController> controller_; | |
| 172 | |
| 173 bool playing_; | |
| 174 }; | |
| 175 | |
| 176 AudioRendererHost::AudioEntry::AudioEntry( | 125 AudioRendererHost::AudioEntry::AudioEntry( |
| 177 AudioRendererHost* host, | 126 AudioRendererHost* host, |
| 178 int stream_id, | 127 int stream_id, |
| 179 int render_frame_id, | 128 int render_frame_id, |
| 180 const media::AudioParameters& params, | 129 const media::AudioParameters& params, |
| 181 const std::string& output_device_id, | 130 const std::string& output_device_id, |
| 182 std::unique_ptr<base::SharedMemory> shared_memory, | 131 std::unique_ptr<base::SharedMemory> shared_memory, |
| 183 std::unique_ptr<media::AudioOutputController::SyncReader> reader) | 132 std::unique_ptr<media::AudioOutputController::SyncReader> reader, |
| 133 const mojom::AudioOutput::CreateStreamCallback& callback) |
| 184 : host_(host), | 134 : host_(host), |
| 185 stream_id_(stream_id), | 135 stream_id_(stream_id), |
| 186 render_frame_id_(render_frame_id), | 136 render_frame_id_(render_frame_id), |
| 187 shared_memory_(std::move(shared_memory)), | 137 shared_memory_(std::move(shared_memory)), |
| 188 reader_(std::move(reader)), | 138 reader_(std::move(reader)), |
| 189 controller_(media::AudioOutputController::Create(host->audio_manager_, | 139 controller_(media::AudioOutputController::Create(host->audio_manager_, |
| 190 this, | 140 this, |
| 191 params, | 141 params, |
| 192 output_device_id, | 142 output_device_id, |
| 193 reader_.get())), | 143 reader_.get(), |
| 144 callback)), |
| 194 playing_(false) { | 145 playing_(false) { |
| 195 DCHECK(controller_.get()); | 146 DCHECK(controller_.get()); |
| 196 } | 147 } |
| 197 | 148 |
| 198 AudioRendererHost::AudioEntry::~AudioEntry() {} | 149 AudioRendererHost::AudioEntry::~AudioEntry() {} |
| 199 | 150 |
| 200 /////////////////////////////////////////////////////////////////////////////// | 151 /////////////////////////////////////////////////////////////////////////////// |
| 201 // AudioRendererHost implementations. | 152 // AudioRendererHost implementations. |
| 202 | 153 |
| 203 AudioRendererHost::AudioRendererHost( | 154 AudioRendererHost::AudioRendererHost( |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 } | 206 } |
| 256 | 207 |
| 257 // Remove any authorizations for streams that were not yet created | 208 // Remove any authorizations for streams that were not yet created |
| 258 authorizations_.clear(); | 209 authorizations_.clear(); |
| 259 } | 210 } |
| 260 | 211 |
| 261 void AudioRendererHost::OnDestruct() const { | 212 void AudioRendererHost::OnDestruct() const { |
| 262 BrowserThread::DeleteOnIOThread::Destruct(this); | 213 BrowserThread::DeleteOnIOThread::Destruct(this); |
| 263 } | 214 } |
| 264 | 215 |
| 265 void AudioRendererHost::AudioEntry::OnCreated() { | 216 void AudioRendererHost::AudioEntry::OnCreated( |
| 266 BrowserThread::PostTask( | 217 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 267 BrowserThread::IO, | 218 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 268 FROM_HERE, | 219 base::Bind(&AudioRendererHost::DoCompleteCreation, |
| 269 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_)); | 220 host_, stream_id_, callback)); |
| 270 } | 221 } |
| 271 | 222 |
| 272 void AudioRendererHost::AudioEntry::OnPlaying() { | 223 void AudioRendererHost::AudioEntry::OnPlaying() { |
| 273 BrowserThread::PostTask( | 224 BrowserThread::PostTask( |
| 274 BrowserThread::IO, | 225 BrowserThread::IO, |
| 275 FROM_HERE, | 226 FROM_HERE, |
| 276 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, | 227 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, |
| 277 host_, | 228 host_, |
| 278 stream_id_, | 229 stream_id_, |
| 279 true)); | 230 true)); |
| 280 } | 231 } |
| 281 | 232 |
| 282 void AudioRendererHost::AudioEntry::OnPaused() { | 233 void AudioRendererHost::AudioEntry::OnPaused() { |
| 283 BrowserThread::PostTask( | 234 BrowserThread::PostTask( |
| 284 BrowserThread::IO, | 235 BrowserThread::IO, |
| 285 FROM_HERE, | 236 FROM_HERE, |
| 286 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, | 237 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, |
| 287 host_, | 238 host_, |
| 288 stream_id_, | 239 stream_id_, |
| 289 false)); | 240 false)); |
| 290 } | 241 } |
| 291 | 242 |
| 292 void AudioRendererHost::AudioEntry::OnError() { | 243 void AudioRendererHost::AudioEntry::OnError() { |
| 293 BrowserThread::PostTask( | 244 BrowserThread::PostTask( |
| 294 BrowserThread::IO, | 245 BrowserThread::IO, |
| 295 FROM_HERE, | 246 FROM_HERE, |
| 296 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); | 247 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); |
| 297 } | 248 } |
| 298 | 249 |
| 299 void AudioRendererHost::DoCompleteCreation(int stream_id) { | 250 void AudioRendererHost::DoCompleteCreation( |
| 251 int stream_id, |
| 252 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 300 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 253 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 301 | 254 |
| 302 if (!PeerHandle()) { | 255 if (!PeerHandle()) { |
| 303 DLOG(WARNING) << "Renderer process handle is invalid."; | 256 DLOG(WARNING) << "Renderer process handle is invalid."; |
| 304 ReportErrorAndClose(stream_id); | 257 ReportErrorAndCloseMojo(stream_id, callback); |
| 305 return; | 258 return; |
| 306 } | 259 } |
| 307 | 260 |
| 308 AudioEntry* const entry = LookupById(stream_id); | 261 AudioEntry* const entry = LookupById(stream_id); |
| 309 if (!entry) { | 262 if (!entry) { |
| 310 ReportErrorAndClose(stream_id); | 263 ReportErrorAndCloseMojo(stream_id, callback); |
| 311 return; | 264 return; |
| 312 } | 265 } |
| 313 | 266 |
| 314 // Once the audio stream is created then complete the creation process by | 267 scoped_ptr<mojom::AudioOutputStreamPtr> stream_ptr( |
| 315 // mapping shared memory and sharing with the renderer process. | 268 audio_output_impl_->StreamFactory(stream_id, entry, this)); |
| 316 base::SharedMemoryHandle foreign_memory_handle; | 269 |
| 317 if (!entry->shared_memory()->ShareToProcess(PeerHandle(), | 270 base::SharedMemoryHandle shared_memory_handle = |
| 318 &foreign_memory_handle)) { | 271 base::SharedMemory::DuplicateHandle(entry->shared_memory()->handle()); |
| 319 // If we failed to map and share the shared memory then close the audio | 272 |
| 320 // stream and send an error message. | 273 MojoHandle mojo_foreign_memory_handle; |
| 321 ReportErrorAndClose(entry->stream_id()); | 274 |
| 275 MojoResult shared_buffer_result = mojo::edk::CreateSharedBufferWrapper( |
| 276 shared_memory_handle, entry->shared_memory()->requested_size(), false, |
| 277 &mojo_foreign_memory_handle); |
| 278 |
| 279 if (shared_buffer_result != MOJO_RESULT_OK) { |
| 280 DLOG(WARNING) << "Failed to wrap transit descriptor. Closing: " |
| 281 << shared_buffer_result; |
| 282 ReportErrorAndCloseMojo(entry->stream_id(), callback); |
| 322 return; | 283 return; |
| 323 } | 284 } |
| 324 | 285 |
| 325 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); | 286 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); |
| 326 | 287 |
| 327 base::SyncSocket::TransitDescriptor socket_descriptor; | 288 base::SyncSocket::TransitDescriptor socket_descriptor; |
| 328 | 289 |
| 329 // If we failed to prepare the sync socket for the renderer then we fail | 290 // If we failed to prepare the sync socket for the renderer then we fail |
| 330 // the construction of audio stream. | 291 // the construction of audio stream. |
| 331 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { | 292 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { |
| 332 ReportErrorAndClose(entry->stream_id()); | 293 ReportErrorAndCloseMojo(entry->stream_id(), callback); |
| 294 return; |
| 295 } |
| 296 mojo::ScopedSharedBufferHandle shared_buffer_handle = |
| 297 mojo::ScopedSharedBufferHandle( |
| 298 mojo::SharedBufferHandle(mojo_foreign_memory_handle)); |
| 299 |
| 300 MojoHandle socket_descriptor_handle; |
| 301 MojoResult platform_handle_result; |
| 302 |
| 303 // Mojo is going to close the socket handle when Mojo shutdowns. |
| 304 // This could create a conflict between Mojo and AudioOutputIPCDelegate where |
| 305 // the socket is going to need to be closed too. |
| 306 // This is why a duplicate of socket handler is going to be created, stored in |
| 307 // |socket_descriptor_dup| and sent through Mojo to the renderer. |
| 308 |
| 309 #if defined(OS_WIN) |
| 310 base::SyncSocket::TransitDescriptor socket_descriptor_dup = nullptr; |
| 311 if (::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle |
| 312 socket_descriptor, |
| 313 GetCurrentProcess(), // hTargetProcessHandle |
| 314 &socket_descriptor_dup, |
| 315 0, // dwDesiredAccess ignored due to SAME_ACCESS |
| 316 FALSE, // !bInheritHandle |
| 317 DUPLICATE_SAME_ACCESS)) { |
| 318 DLOG(WARNING) << "Failed to duplicate socket"; |
| 319 return; |
| 320 } |
| 321 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( |
| 322 mojo::edk::ScopedPlatformHandle( |
| 323 mojo::edk::PlatformHandle(socket_descriptor_dup)), |
| 324 &socket_descriptor_handle); |
| 325 |
| 326 #else |
| 327 int socket_descriptor_dup = dup(socket_descriptor.fd); |
| 328 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( |
| 329 mojo::edk::ScopedPlatformHandle( |
| 330 mojo::edk::PlatformHandle(socket_descriptor_dup)), |
| 331 &socket_descriptor_handle); |
| 332 #endif |
| 333 |
| 334 if (platform_handle_result != MOJO_RESULT_OK) { |
| 335 DLOG(WARNING) << "Failed to wrap platform handle. Closing: " |
| 336 << platform_handle_result; |
| 337 ReportErrorAndCloseMojo(stream_id, callback); |
| 333 return; | 338 return; |
| 334 } | 339 } |
| 335 | 340 |
| 336 Send(new AudioMsg_NotifyStreamCreated( | 341 mojo::ScopedHandle socket_handle = |
| 337 entry->stream_id(), foreign_memory_handle, socket_descriptor, | 342 mojo::ScopedHandle(mojo::Handle(socket_descriptor_handle)); |
| 338 entry->shared_memory()->requested_size())); | 343 callback.Run(std::move(*stream_ptr), stream_id, |
| 344 std::move(shared_buffer_handle), std::move(socket_handle)); |
| 345 |
| 339 } | 346 } |
| 340 | 347 |
| 341 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, | 348 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, |
| 342 bool is_playing) { | 349 bool is_playing) { |
| 343 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 350 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 344 | 351 |
| 345 AudioEntry* const entry = LookupById(stream_id); | 352 AudioEntry* const entry = LookupById(stream_id); |
| 346 if (!entry) | 353 if (!entry) |
| 347 return; | 354 return; |
| 348 | 355 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 379 return controllers; | 386 return controllers; |
| 380 } | 387 } |
| 381 | 388 |
| 382 /////////////////////////////////////////////////////////////////////////////// | 389 /////////////////////////////////////////////////////////////////////////////// |
| 383 // IPC Messages handler | 390 // IPC Messages handler |
| 384 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { | 391 bool AudioRendererHost::OnMessageReceived(const IPC::Message& message) { |
| 385 bool handled = true; | 392 bool handled = true; |
| 386 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) | 393 IPC_BEGIN_MESSAGE_MAP(AudioRendererHost, message) |
| 387 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization, | 394 IPC_MESSAGE_HANDLER(AudioHostMsg_RequestDeviceAuthorization, |
| 388 OnRequestDeviceAuthorization) | 395 OnRequestDeviceAuthorization) |
| 389 IPC_MESSAGE_HANDLER(AudioHostMsg_CreateStream, OnCreateStream) | |
| 390 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) | 396 IPC_MESSAGE_HANDLER(AudioHostMsg_PlayStream, OnPlayStream) |
| 391 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) | 397 IPC_MESSAGE_HANDLER(AudioHostMsg_PauseStream, OnPauseStream) |
| 392 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) | 398 IPC_MESSAGE_HANDLER(AudioHostMsg_CloseStream, OnCloseStream) |
| 393 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) | 399 IPC_MESSAGE_HANDLER(AudioHostMsg_SetVolume, OnSetVolume) |
| 394 IPC_MESSAGE_UNHANDLED(handled = false) | 400 IPC_MESSAGE_UNHANDLED(handled = false) |
| 395 IPC_END_MESSAGE_MAP() | 401 IPC_END_MESSAGE_MAP() |
| 396 | 402 |
| 397 return handled; | 403 return handled; |
| 398 } | 404 } |
| 399 | 405 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 | 524 |
| 519 auth_data->second.first = true; | 525 auth_data->second.first = true; |
| 520 auth_data->second.second = device_info.unique_id; | 526 auth_data->second.second = device_info.unique_id; |
| 521 | 527 |
| 522 media::AudioParameters output_params = device_info.output_params; | 528 media::AudioParameters output_params = device_info.output_params; |
| 523 MaybeFixAudioParameters(&output_params); | 529 MaybeFixAudioParameters(&output_params); |
| 524 Send(new AudioMsg_NotifyDeviceAuthorized( | 530 Send(new AudioMsg_NotifyDeviceAuthorized( |
| 525 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); | 531 stream_id, media::OUTPUT_DEVICE_STATUS_OK, output_params, std::string())); |
| 526 } | 532 } |
| 527 | 533 |
| 528 void AudioRendererHost::OnCreateStream(int stream_id, | 534 void AudioRendererHost::OnCreateStream( |
| 529 int render_frame_id, | 535 int stream_id, |
| 530 const media::AudioParameters& params) { | 536 int render_frame_id, |
| 537 const media::AudioParameters& params, |
| 538 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 531 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 539 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 532 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" | 540 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" |
| 533 << "(stream_id=" << stream_id << ")"; | 541 << "(stream_id=" << stream_id << ")"; |
| 534 | 542 |
| 535 const auto& auth_data = authorizations_.find(stream_id); | 543 const auto& auth_data = authorizations_.find(stream_id); |
| 536 | 544 |
| 537 // If no previous authorization requested, assume default device | 545 // If no previous authorization requested, assume default device |
| 538 if (auth_data == authorizations_.end()) { | 546 if (auth_data == authorizations_.end()) { |
| 539 DoCreateStream(stream_id, render_frame_id, params, std::string()); | 547 DoCreateStream(stream_id, render_frame_id, params, std::string(), callback); |
| 540 return; | 548 return; |
| 541 } | 549 } |
| 542 | 550 |
| 543 CHECK(auth_data->second.first); | 551 CHECK(auth_data->second.first); |
| 544 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second); | 552 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second, |
| 553 callback); |
| 545 authorizations_.erase(auth_data); | 554 authorizations_.erase(auth_data); |
| 546 } | 555 } |
| 547 | 556 |
| 548 void AudioRendererHost::DoCreateStream(int stream_id, | 557 void AudioRendererHost::DoCreateStream( |
| 549 int render_frame_id, | 558 int stream_id, |
| 550 const media::AudioParameters& params, | 559 int render_frame_id, |
| 551 const std::string& device_unique_id) { | 560 const media::AudioParameters& params, |
| 561 const std::string& device_unique_id, |
| 562 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 552 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 563 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 553 | 564 |
| 554 // media::AudioParameters is validated in the deserializer. | 565 // media::AudioParameters is validated in the deserializer. |
| 555 if (LookupById(stream_id) != NULL) { | 566 if (LookupById(stream_id) != NULL) { |
| 556 SendErrorMessage(stream_id); | 567 SendErrorMessage(stream_id); |
| 557 return; | 568 return; |
| 558 } | 569 } |
| 559 | 570 |
| 560 // Create the shared memory and share with the renderer process. | 571 // Create the shared memory and share with the renderer process. |
| 561 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) + | 572 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) + |
| 562 AudioBus::CalculateMemorySize(params); | 573 AudioBus::CalculateMemorySize(params); |
| 563 std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); | 574 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); |
| 564 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) { | 575 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) { |
| 565 SendErrorMessage(stream_id); | 576 SendErrorMessage(stream_id); |
| 566 return; | 577 return; |
| 567 } | 578 } |
| 568 | 579 |
| 569 std::unique_ptr<AudioSyncReader> reader( | 580 scoped_ptr<AudioSyncReader> reader( |
| 570 new AudioSyncReader(shared_memory.get(), params)); | 581 new AudioSyncReader(shared_memory.get(), params)); |
| 571 if (!reader->Init()) { | 582 if (!reader->Init()) { |
| 572 SendErrorMessage(stream_id); | 583 SendErrorMessage(stream_id); |
| 573 return; | 584 return; |
| 574 } | 585 } |
| 575 | 586 |
| 576 MediaObserver* const media_observer = | 587 MediaObserver* const media_observer = |
| 577 GetContentClient()->browser()->GetMediaObserver(); | 588 GetContentClient()->browser()->GetMediaObserver(); |
| 578 if (media_observer) | 589 if (media_observer) |
| 579 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); | 590 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); |
| 580 | 591 |
| 581 std::unique_ptr<AudioEntry> entry( | 592 scoped_ptr<AudioEntry> entry( |
| 582 new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id, | 593 new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id, |
| 583 std::move(shared_memory), std::move(reader))); | 594 std::move(shared_memory), std::move(reader), callback)); |
| 584 if (mirroring_manager_) { | 595 if (mirroring_manager_) { |
| 585 mirroring_manager_->AddDiverter( | 596 mirroring_manager_->AddDiverter( |
| 586 render_process_id_, entry->render_frame_id(), entry->controller()); | 597 render_process_id_, entry->render_frame_id(), entry->controller()); |
| 587 } | 598 } |
| 588 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 599 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
| 589 g_audio_streams_tracker.Get().IncreaseStreamCount(); | 600 g_audio_streams_tracker.Get().IncreaseStreamCount(); |
| 590 | 601 |
| 591 audio_log_->OnCreated(stream_id, params, device_unique_id); | 602 audio_log_->OnCreated(stream_id, params, device_unique_id); |
| 592 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( | 603 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( |
| 593 stream_id, render_process_id_, render_frame_id, audio_log_.get()); | 604 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. | 697 // is closed. |
| 687 if (!LookupById(stream_id)) | 698 if (!LookupById(stream_id)) |
| 688 return; | 699 return; |
| 689 | 700 |
| 690 SendErrorMessage(stream_id); | 701 SendErrorMessage(stream_id); |
| 691 | 702 |
| 692 audio_log_->OnError(stream_id); | 703 audio_log_->OnError(stream_id); |
| 693 OnCloseStream(stream_id); | 704 OnCloseStream(stream_id); |
| 694 } | 705 } |
| 695 | 706 |
| 707 void AudioRendererHost::ReportErrorAndCloseMojo( |
| 708 int stream_id, |
| 709 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 710 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 711 |
| 712 // Make sure this isn't a stray callback executing after the stream has been |
| 713 // closed, so error notifications aren't sent after clients believe the stream |
| 714 // is closed. |
| 715 if (!LookupById(stream_id)) |
| 716 return; |
| 717 mojo::ScopedSharedBufferHandle shared_buffer_handle = |
| 718 mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle()); |
| 719 |
| 720 mojo::ScopedHandle socket_handle = mojo::ScopedHandle(mojo::Handle()); |
| 721 |
| 722 callback.Run(mojom::AudioOutputStreamPtr(), stream_id, |
| 723 std::move(shared_buffer_handle), std::move(socket_handle)); |
| 724 |
| 725 audio_log_->OnError(stream_id); |
| 726 OnCloseStream(stream_id); |
| 727 } |
| 728 |
| 696 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { | 729 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
| 697 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 730 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 698 | 731 |
| 699 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); | 732 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); |
| 700 return i != audio_entries_.end() ? i->second : NULL; | 733 return i != audio_entries_.end() ? i->second : NULL; |
| 701 } | 734 } |
| 702 | 735 |
| 703 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, | 736 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, |
| 704 bool is_playing) { | 737 bool is_playing) { |
| 705 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 738 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 callback.Run(false, device_info); | 848 callback.Run(false, device_info); |
| 816 } | 849 } |
| 817 | 850 |
| 818 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { | 851 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { |
| 819 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 852 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 820 const auto& i = authorizations_.find(stream_id); | 853 const auto& i = authorizations_.find(stream_id); |
| 821 return i != authorizations_.end(); | 854 return i != authorizations_.end(); |
| 822 } | 855 } |
| 823 | 856 |
| 824 } // namespace content | 857 } // namespace content |
| OLD | NEW |