| 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 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/shared_memory.h" | |
| 15 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 16 #include "base/process/process.h" | 15 #include "base/process/process.h" |
| 17 #include "content/browser/bad_message.h" | 16 #include "content/browser/bad_message.h" |
| 18 #include "content/browser/browser_main_loop.h" | 17 #include "content/browser/browser_main_loop.h" |
| 19 #include "content/browser/child_process_security_policy_impl.h" | 18 #include "content/browser/child_process_security_policy_impl.h" |
| 20 #include "content/browser/media/audio_stream_monitor.h" | 19 #include "content/browser/media/audio_stream_monitor.h" |
| 21 #include "content/browser/media/capture/audio_mirroring_manager.h" | 20 #include "content/browser/media/capture/audio_mirroring_manager.h" |
| 22 #include "content/browser/media/media_internals.h" | 21 #include "content/browser/media/media_internals.h" |
| 23 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 22 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
| 24 #include "content/browser/renderer_host/media/audio_sync_reader.h" | 23 #include "content/browser/renderer_host/media/audio_sync_reader.h" |
| 25 #include "content/browser/renderer_host/media/media_stream_manager.h" | 24 #include "content/browser/renderer_host/media/media_stream_manager.h" |
| 26 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" | 25 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" |
| 27 #include "content/browser/renderer_host/render_widget_host_impl.h" | 26 #include "content/browser/renderer_host/render_widget_host_impl.h" |
| 28 #include "content/common/media/audio_messages.h" | 27 #include "content/common/media/audio_messages.h" |
| 29 #include "content/public/browser/content_browser_client.h" | 28 #include "content/public/browser/content_browser_client.h" |
| 30 #include "content/public/browser/media_device_id.h" | 29 #include "content/public/browser/media_device_id.h" |
| 31 #include "content/public/browser/media_observer.h" | 30 #include "content/public/browser/media_observer.h" |
| 32 #include "content/public/browser/render_frame_host.h" | 31 #include "content/public/browser/render_frame_host.h" |
| 33 #include "content/public/common/content_switches.h" | 32 #include "content/public/common/content_switches.h" |
| 33 #include "content/renderer/media/audio_output_client.h" |
| 34 #include "media/audio/audio_device_name.h" | 34 #include "media/audio/audio_device_name.h" |
| 35 #include "media/audio/audio_manager_base.h" | 35 #include "media/audio/audio_manager_base.h" |
| 36 #include "media/audio/audio_streams_tracker.h" | 36 #include "media/audio/audio_streams_tracker.h" |
| 37 #include "media/base/audio_bus.h" | 37 #include "media/base/audio_bus.h" |
| 38 #include "media/base/limits.h" | 38 #include "media/base/limits.h" |
| 39 #include "mojo/edk/embedder/embedder.h" |
| 40 #include "mojo/public/cpp/system/handle.h" |
| 41 #include "base/time/time.h" |
| 42 |
| 43 #include "content/browser/media/audio_output_impl.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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 115 params->set_channels_for_discrete(media::limits::kMaxChannels); | 120 params->set_channels_for_discrete(media::limits::kMaxChannels); |
| 116 | 121 |
| 117 // If hardware parameters are still invalid, use dummy parameters with | 122 // If hardware parameters are still invalid, use dummy parameters with |
| 118 // fake audio path and let the client handle the error. | 123 // fake audio path and let the client handle the error. |
| 119 if (!params->IsValid()) | 124 if (!params->IsValid()) |
| 120 *params = media::AudioParameters::UnavailableDeviceParams(); | 125 *params = media::AudioParameters::UnavailableDeviceParams(); |
| 121 } | 126 } |
| 122 | 127 |
| 123 } // namespace | 128 } // namespace |
| 124 | 129 |
| 125 class AudioRendererHost::AudioEntry | 130 AudioEntry::AudioEntry( |
| 126 : public media::AudioOutputController::EventHandler { | |
| 127 public: | |
| 128 AudioEntry(AudioRendererHost* host, | |
| 129 int stream_id, | |
| 130 int render_frame_id, | |
| 131 const media::AudioParameters& params, | |
| 132 const std::string& output_device_id, | |
| 133 scoped_ptr<base::SharedMemory> shared_memory, | |
| 134 scoped_ptr<media::AudioOutputController::SyncReader> reader); | |
| 135 ~AudioEntry() override; | |
| 136 | |
| 137 int stream_id() const { | |
| 138 return stream_id_; | |
| 139 } | |
| 140 | |
| 141 int render_frame_id() const { return render_frame_id_; } | |
| 142 | |
| 143 media::AudioOutputController* controller() const { return controller_.get(); } | |
| 144 | |
| 145 base::SharedMemory* shared_memory() { | |
| 146 return shared_memory_.get(); | |
| 147 } | |
| 148 | |
| 149 media::AudioOutputController::SyncReader* reader() const { | |
| 150 return reader_.get(); | |
| 151 } | |
| 152 | |
| 153 bool playing() const { return playing_; } | |
| 154 void set_playing(bool playing) { playing_ = playing; } | |
| 155 | |
| 156 private: | |
| 157 // media::AudioOutputController::EventHandler implementation. | |
| 158 void OnCreated() override; | |
| 159 void OnPlaying() override; | |
| 160 void OnPaused() override; | |
| 161 void OnError() override; | |
| 162 | |
| 163 AudioRendererHost* const host_; | |
| 164 const int stream_id_; | |
| 165 | |
| 166 // The routing ID of the source RenderFrame. | |
| 167 const int render_frame_id_; | |
| 168 | |
| 169 // Shared memory for transmission of the audio data. Used by |reader_|. | |
| 170 const scoped_ptr<base::SharedMemory> shared_memory_; | |
| 171 | |
| 172 // The synchronous reader to be used by |controller_|. | |
| 173 const scoped_ptr<media::AudioOutputController::SyncReader> reader_; | |
| 174 | |
| 175 // The AudioOutputController that manages the audio stream. | |
| 176 const scoped_refptr<media::AudioOutputController> controller_; | |
| 177 | |
| 178 bool playing_; | |
| 179 }; | |
| 180 | |
| 181 AudioRendererHost::AudioEntry::AudioEntry( | |
| 182 AudioRendererHost* host, | 131 AudioRendererHost* host, |
| 183 int stream_id, | 132 int stream_id, |
| 184 int render_frame_id, | 133 int render_frame_id, |
| 185 const media::AudioParameters& params, | 134 const media::AudioParameters& params, |
| 186 const std::string& output_device_id, | 135 const std::string& output_device_id, |
| 187 scoped_ptr<base::SharedMemory> shared_memory, | 136 scoped_ptr<base::SharedMemory> shared_memory, |
| 188 scoped_ptr<media::AudioOutputController::SyncReader> reader) | 137 scoped_ptr<media::AudioOutputController::SyncReader> reader) |
| 189 : host_(host), | 138 : host_(host), |
| 190 stream_id_(stream_id), | 139 stream_id_(stream_id), |
| 191 render_frame_id_(render_frame_id), | 140 render_frame_id_(render_frame_id), |
| 192 shared_memory_(std::move(shared_memory)), | 141 shared_memory_(std::move(shared_memory)), |
| 193 reader_(std::move(reader)), | 142 reader_(std::move(reader)), |
| 194 controller_(media::AudioOutputController::Create(host->audio_manager_, | 143 controller_(media::AudioOutputController::Create(host->audio_manager_, |
| 195 this, | 144 this, |
| 196 params, | 145 params, |
| 197 output_device_id, | 146 output_device_id, |
| 198 reader_.get())), | 147 reader_.get())), |
| 199 playing_(false) { | 148 playing_(false) { |
| 200 DCHECK(controller_.get()); | 149 DCHECK(controller_.get()); |
| 201 } | 150 } |
| 202 | 151 |
| 203 AudioRendererHost::AudioEntry::~AudioEntry() {} | 152 AudioEntry::AudioEntry( |
| 153 AudioRendererHost* host, |
| 154 int stream_id, |
| 155 int render_frame_id, |
| 156 const media::AudioParameters& params, |
| 157 const std::string& output_device_id, |
| 158 scoped_ptr<base::SharedMemory> shared_memory, |
| 159 scoped_ptr<media::AudioOutputController::SyncReader> reader, |
| 160 mojom::AudioOutputStreamPtr stream, |
| 161 const mojom::AudioOutput::CreateStreamCallback& callback) |
| 162 : host_(host), |
| 163 stream_id_(stream_id), |
| 164 render_frame_id_(render_frame_id), |
| 165 shared_memory_(std::move(shared_memory)), |
| 166 reader_(std::move(reader)), |
| 167 controller_(media::AudioOutputController::Create(host->audio_manager_, |
| 168 this, |
| 169 params, |
| 170 output_device_id, |
| 171 reader_.get(), |
| 172 std::move(stream), |
| 173 callback)), |
| 174 playing_(false) { |
| 175 DCHECK(controller_.get()); |
| 176 } |
| 177 |
| 178 AudioEntry::~AudioEntry() {} |
| 204 | 179 |
| 205 /////////////////////////////////////////////////////////////////////////////// | 180 /////////////////////////////////////////////////////////////////////////////// |
| 206 // AudioRendererHost implementations. | 181 // AudioRendererHost implementations. |
| 207 | 182 |
| 208 AudioRendererHost::AudioRendererHost( | 183 AudioRendererHost::AudioRendererHost( |
| 209 int render_process_id, | 184 int render_process_id, |
| 210 media::AudioManager* audio_manager, | 185 media::AudioManager* audio_manager, |
| 211 AudioMirroringManager* mirroring_manager, | 186 AudioMirroringManager* mirroring_manager, |
| 212 MediaInternals* media_internals, | 187 MediaInternals* media_internals, |
| 213 MediaStreamManager* media_stream_manager, | 188 MediaStreamManager* media_stream_manager, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 260 } | 235 } |
| 261 | 236 |
| 262 // Remove any authorizations for streams that were not yet created | 237 // Remove any authorizations for streams that were not yet created |
| 263 authorizations_.clear(); | 238 authorizations_.clear(); |
| 264 } | 239 } |
| 265 | 240 |
| 266 void AudioRendererHost::OnDestruct() const { | 241 void AudioRendererHost::OnDestruct() const { |
| 267 BrowserThread::DeleteOnIOThread::Destruct(this); | 242 BrowserThread::DeleteOnIOThread::Destruct(this); |
| 268 } | 243 } |
| 269 | 244 |
| 270 void AudioRendererHost::AudioEntry::OnCreated() { | 245 void AudioEntry::OnCreated() { |
| 271 BrowserThread::PostTask( | 246 BrowserThread::PostTask( |
| 272 BrowserThread::IO, | 247 BrowserThread::IO, |
| 273 FROM_HERE, | 248 FROM_HERE, |
| 274 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_)); | 249 base::Bind(&AudioRendererHost::DoCompleteCreation, host_, stream_id_)); |
| 275 } | 250 } |
| 276 | 251 |
| 277 void AudioRendererHost::AudioEntry::OnPlaying() { | 252 void AudioEntry::OnCreated( |
| 253 mojom::AudioOutputStreamPtr stream, |
| 254 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 255 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 256 base::Bind(&AudioRendererHost::DoCompleteCreationMojo, |
| 257 host_, stream_id_, callback)); |
| 258 } |
| 259 |
| 260 void AudioEntry::OnPlaying() { |
| 278 BrowserThread::PostTask( | 261 BrowserThread::PostTask( |
| 279 BrowserThread::IO, | 262 BrowserThread::IO, |
| 280 FROM_HERE, | 263 FROM_HERE, |
| 281 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, | 264 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, |
| 282 host_, | 265 host_, |
| 283 stream_id_, | 266 stream_id_, |
| 284 true)); | 267 true)); |
| 285 } | 268 } |
| 286 | 269 |
| 287 void AudioRendererHost::AudioEntry::OnPaused() { | 270 void AudioEntry::OnPaused() { |
| 288 BrowserThread::PostTask( | 271 BrowserThread::PostTask( |
| 289 BrowserThread::IO, | 272 BrowserThread::IO, |
| 290 FROM_HERE, | 273 FROM_HERE, |
| 291 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, | 274 base::Bind(&AudioRendererHost::DoNotifyStreamStateChanged, |
| 292 host_, | 275 host_, |
| 293 stream_id_, | 276 stream_id_, |
| 294 false)); | 277 false)); |
| 295 } | 278 } |
| 296 | 279 |
| 297 void AudioRendererHost::AudioEntry::OnError() { | 280 void AudioEntry::OnError() { |
| 298 BrowserThread::PostTask( | 281 BrowserThread::PostTask( |
| 299 BrowserThread::IO, | 282 BrowserThread::IO, |
| 300 FROM_HERE, | 283 FROM_HERE, |
| 301 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); | 284 base::Bind(&AudioRendererHost::ReportErrorAndClose, host_, stream_id_)); |
| 302 } | 285 } |
| 303 | 286 |
| 304 void AudioRendererHost::DoCompleteCreation(int stream_id) { | 287 void AudioRendererHost::DoCompleteCreation(int stream_id) { |
| 305 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 288 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 306 | 289 |
| 307 if (!PeerHandle()) { | 290 if (!PeerHandle()) { |
| 308 DLOG(WARNING) << "Renderer process handle is invalid."; | 291 DLOG(WARNING) << "Renderer process handle is invalid."; |
| 309 ReportErrorAndClose(stream_id); | 292 // ReportErrorAndClose(stream_id); |
| 310 return; | 293 return; |
| 311 } | 294 } |
| 312 | 295 |
| 313 AudioEntry* const entry = LookupById(stream_id); | 296 AudioEntry* const entry = LookupById(stream_id); |
| 314 if (!entry) { | 297 if (!entry) { |
| 315 ReportErrorAndClose(stream_id); | 298 // ReportErrorAndClose(stream_id); |
| 316 return; | 299 return; |
| 317 } | 300 } |
| 318 | 301 |
| 319 // Once the audio stream is created then complete the creation process by | 302 // Once the audio stream is created then complete the creation process by |
| 320 // mapping shared memory and sharing with the renderer process. | 303 // mapping shared memory and sharing with the renderer process. |
| 321 base::SharedMemoryHandle foreign_memory_handle; | 304 base::SharedMemoryHandle foreign_memory_handle; |
| 322 if (!entry->shared_memory()->ShareToProcess(PeerHandle(), | 305 if (!entry->shared_memory()->ShareToProcess(PeerHandle(), |
| 323 &foreign_memory_handle)) { | 306 &foreign_memory_handle)) { |
| 324 // If we failed to map and share the shared memory then close the audio | 307 // If we failed to map and share the shared memory then close the audio |
| 325 // stream and send an error message. | 308 // stream and send an error message. |
| 326 ReportErrorAndClose(entry->stream_id()); | 309 // ReportErrorAndClose(entry->stream_id()); |
| 327 return; | 310 return; |
| 328 } | 311 } |
| 329 | 312 |
| 330 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); | 313 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); |
| 331 | 314 |
| 332 base::SyncSocket::TransitDescriptor socket_descriptor; | 315 base::SyncSocket::TransitDescriptor socket_descriptor; |
| 333 | 316 |
| 334 // If we failed to prepare the sync socket for the renderer then we fail | 317 // If we failed to prepare the sync socket for the renderer then we fail |
| 335 // the construction of audio stream. | 318 // the construction of audio stream. |
| 336 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { | 319 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { |
| 337 ReportErrorAndClose(entry->stream_id()); | 320 // ReportErrorAndClose(entry->stream_id()); |
| 338 return; | 321 return; |
| 339 } | 322 } |
| 340 | 323 |
| 341 Send(new AudioMsg_NotifyStreamCreated( | 324 Send(new AudioMsg_NotifyStreamCreated( |
| 342 entry->stream_id(), foreign_memory_handle, socket_descriptor, | 325 entry->stream_id(), foreign_memory_handle, socket_descriptor, |
| 343 entry->shared_memory()->requested_size())); | 326 entry->shared_memory()->requested_size())); |
| 344 } | 327 } |
| 345 | 328 |
| 329 void AudioRendererHost::DoCompleteCreationMojo( |
| 330 int stream_id, |
| 331 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 332 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 333 |
| 334 if (!PeerHandle()) { |
| 335 DLOG(WARNING) << "Renderer process handle is invalid."; |
| 336 ReportErrorAndCloseMojo(stream_id, callback); |
| 337 return; |
| 338 } |
| 339 |
| 340 AudioEntry* const entry = LookupById(stream_id); |
| 341 if (!entry) { |
| 342 ReportErrorAndCloseMojo(stream_id, callback); |
| 343 return; |
| 344 } |
| 345 |
| 346 scoped_ptr<mojom::AudioOutputStreamPtr> stream_ptr( |
| 347 AudioOutputImpl::CreateStream(entry, stream_id)); |
| 348 |
| 349 base::SharedMemoryHandle shared_memory_handle = |
| 350 base::SharedMemory::DuplicateHandle(entry->shared_memory()->handle()); |
| 351 |
| 352 MojoHandle mojo_foreign_memory_handle; |
| 353 |
| 354 MojoResult shared_buffer_result = mojo::edk::CreateSharedBufferWrapper( |
| 355 shared_memory_handle, entry->shared_memory()->requested_size(), false, |
| 356 &mojo_foreign_memory_handle); |
| 357 |
| 358 if (shared_buffer_result != MOJO_RESULT_OK) { |
| 359 LOG(WARNING) << "Failed to wrap transit descriptor. Closing: " |
| 360 << shared_buffer_result; |
| 361 ReportErrorAndCloseMojo(entry->stream_id(), callback); |
| 362 return; |
| 363 } |
| 364 |
| 365 AudioSyncReader* reader = static_cast<AudioSyncReader*>(entry->reader()); |
| 366 |
| 367 base::SyncSocket::TransitDescriptor socket_descriptor; |
| 368 |
| 369 // If we failed to prepare the sync socket for the renderer then we fail |
| 370 // the construction of audio stream. |
| 371 if (!reader->PrepareForeignSocket(PeerHandle(), &socket_descriptor)) { |
| 372 ReportErrorAndCloseMojo(entry->stream_id(), callback); |
| 373 return; |
| 374 } |
| 375 mojo::ScopedSharedBufferHandle shared_buffer_handle = |
| 376 mojo::ScopedSharedBufferHandle( |
| 377 mojo::SharedBufferHandle(mojo_foreign_memory_handle)); |
| 378 |
| 379 MojoHandle socket_descriptor_handle; |
| 380 MojoResult platform_handle_result; |
| 381 |
| 382 #if defined(OS_WIN) |
| 383 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( |
| 384 mojo::edk::ScopedPlatformHandle( |
| 385 mojo::edk::PlatformHandle(socket_descriptor)), |
| 386 &socket_descriptor_handle); |
| 387 #else |
| 388 platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( |
| 389 mojo::edk::ScopedPlatformHandle( |
| 390 mojo::edk::PlatformHandle(socket_descriptor.fd)), |
| 391 &socket_descriptor_handle); |
| 392 LOG(WARNING) << "socket_descriptor.fd" << socket_descriptor.fd; |
| 393 LOG(WARNING) << "socket_descriptor_handle" << socket_descriptor_handle; |
| 394 #endif |
| 395 |
| 396 if (platform_handle_result != MOJO_RESULT_OK) { |
| 397 LOG(WARNING) << "Failed to wrap platform handle. Closing: " |
| 398 << platform_handle_result; |
| 399 ReportErrorAndCloseMojo(stream_id, callback); |
| 400 return; |
| 401 } |
| 402 |
| 403 stream_ptr->get()->set(20); |
| 404 mojo::ScopedHandle socket_handle = |
| 405 mojo::ScopedHandle(mojo::Handle(socket_descriptor_handle)); |
| 406 |
| 407 LOG(ERROR) << "stream_id" << stream_id; |
| 408 // LOG(ERROR) << "foreign_memory_handle.fd" << foreign_memory_handle.fd; |
| 409 // LOG(ERROR) << "foreign_memory_handle.auto_close" << |
| 410 // foreign_memory_handle.auto_close; |
| 411 LOG(ERROR) << "socket_descriptor.fd" << socket_descriptor.fd; |
| 412 LOG(ERROR) << "socket_descriptor.auto_close" << socket_descriptor.auto_close; |
| 413 LOG(ERROR) << "entry->shared_memory()->requested_size()" |
| 414 << entry->shared_memory()->requested_size(); |
| 415 LOG(ERROR) << "AudioRendererHost::DoCompleteCreationMojo" |
| 416 << base::TimeTicks::Now(); |
| 417 |
| 418 callback.Run(std::move(*stream_ptr), stream_id, |
| 419 std::move(shared_buffer_handle), std::move(socket_handle)); |
| 420 } |
| 421 |
| 346 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, | 422 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id, |
| 347 bool is_playing) { | 423 bool is_playing) { |
| 348 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 424 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 349 | 425 |
| 350 AudioEntry* const entry = LookupById(stream_id); | 426 AudioEntry* const entry = LookupById(stream_id); |
| 351 if (!entry) | 427 if (!entry) |
| 352 return; | 428 return; |
| 353 | 429 |
| 354 Send(new AudioMsg_NotifyStreamStateChanged( | 430 Send(new AudioMsg_NotifyStreamStateChanged( |
| 355 stream_id, | 431 stream_id, |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 if (auth_data == authorizations_.end()) { | 618 if (auth_data == authorizations_.end()) { |
| 543 DoCreateStream(stream_id, render_frame_id, params, std::string()); | 619 DoCreateStream(stream_id, render_frame_id, params, std::string()); |
| 544 return; | 620 return; |
| 545 } | 621 } |
| 546 | 622 |
| 547 CHECK(auth_data->second.first); | 623 CHECK(auth_data->second.first); |
| 548 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second); | 624 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second); |
| 549 authorizations_.erase(auth_data); | 625 authorizations_.erase(auth_data); |
| 550 } | 626 } |
| 551 | 627 |
| 628 void AudioRendererHost::OnCreateStreamMojo( |
| 629 int stream_id, |
| 630 int render_frame_id, |
| 631 const media::AudioParameters& params, |
| 632 mojom::AudioOutputStreamPtr stream, |
| 633 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 634 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 635 DVLOG(1) << "AudioRendererHost@" << this << "::OnCreateStream" |
| 636 << "(stream_id=" << stream_id << ")"; |
| 637 LOG(ERROR) << "stream_id" << stream_id; |
| 638 |
| 639 const auto& auth_data = authorizations_.find(stream_id); |
| 640 |
| 641 // If no previous authorization requested, assume default device |
| 642 if (auth_data == authorizations_.end()) { |
| 643 DoCreateStream(stream_id, render_frame_id, params, std::string(), |
| 644 std::move(stream), callback); |
| 645 return; |
| 646 } |
| 647 |
| 648 CHECK(auth_data->second.first); |
| 649 DoCreateStream(stream_id, render_frame_id, params, auth_data->second.second, |
| 650 std::move(stream), callback); |
| 651 authorizations_.erase(auth_data); |
| 652 } |
| 653 |
| 552 void AudioRendererHost::DoCreateStream(int stream_id, | 654 void AudioRendererHost::DoCreateStream(int stream_id, |
| 553 int render_frame_id, | 655 int render_frame_id, |
| 554 const media::AudioParameters& params, | 656 const media::AudioParameters& params, |
| 555 const std::string& device_unique_id) { | 657 const std::string& device_unique_id) { |
| 556 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 658 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 557 | 659 |
| 558 // media::AudioParameters is validated in the deserializer. | 660 // media::AudioParameters is validated in the deserializer. |
| 559 if (LookupById(stream_id) != NULL) { | 661 if (LookupById(stream_id) != NULL) { |
| 560 SendErrorMessage(stream_id); | 662 SendErrorMessage(stream_id); |
| 561 return; | 663 return; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 g_audio_streams_tracker.Get().IncreaseStreamCount(); | 695 g_audio_streams_tracker.Get().IncreaseStreamCount(); |
| 594 | 696 |
| 595 audio_log_->OnCreated(stream_id, params, device_unique_id); | 697 audio_log_->OnCreated(stream_id, params, device_unique_id); |
| 596 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( | 698 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( |
| 597 stream_id, render_process_id_, render_frame_id, audio_log_.get()); | 699 stream_id, render_process_id_, render_frame_id, audio_log_.get()); |
| 598 | 700 |
| 599 if (audio_entries_.size() > max_simultaneous_streams_) | 701 if (audio_entries_.size() > max_simultaneous_streams_) |
| 600 max_simultaneous_streams_ = audio_entries_.size(); | 702 max_simultaneous_streams_ = audio_entries_.size(); |
| 601 } | 703 } |
| 602 | 704 |
| 705 void AudioRendererHost::DoCreateStream( |
| 706 int stream_id, |
| 707 int render_frame_id, |
| 708 const media::AudioParameters& params, |
| 709 const std::string& device_unique_id, |
| 710 mojom::AudioOutputStreamPtr stream, |
| 711 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 712 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 713 |
| 714 // media::AudioParameters is validated in the deserializer. |
| 715 if (LookupById(stream_id) != NULL) { |
| 716 SendErrorMessage(stream_id); |
| 717 return; |
| 718 } |
| 719 |
| 720 // Create the shared memory and share with the renderer process. |
| 721 uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) + |
| 722 AudioBus::CalculateMemorySize(params); |
| 723 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); |
| 724 if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) { |
| 725 SendErrorMessage(stream_id); |
| 726 return; |
| 727 } |
| 728 |
| 729 scoped_ptr<AudioSyncReader> reader( |
| 730 new AudioSyncReader(shared_memory.get(), params)); |
| 731 if (!reader->Init()) { |
| 732 SendErrorMessage(stream_id); |
| 733 return; |
| 734 } |
| 735 |
| 736 MediaObserver* const media_observer = |
| 737 GetContentClient()->browser()->GetMediaObserver(); |
| 738 if (media_observer) |
| 739 media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id); |
| 740 |
| 741 scoped_ptr<AudioEntry> entry( |
| 742 new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id, |
| 743 std::move(shared_memory), std::move(reader), |
| 744 std::move(stream), callback)); |
| 745 if (mirroring_manager_) { |
| 746 mirroring_manager_->AddDiverter( |
| 747 render_process_id_, entry->render_frame_id(), entry->controller()); |
| 748 } |
| 749 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
| 750 g_audio_streams_tracker.Get().IncreaseStreamCount(); |
| 751 |
| 752 audio_log_->OnCreated(stream_id, params, device_unique_id); |
| 753 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( |
| 754 stream_id, render_process_id_, render_frame_id, audio_log_.get()); |
| 755 |
| 756 if (audio_entries_.size() > max_simultaneous_streams_) |
| 757 max_simultaneous_streams_ = audio_entries_.size(); |
| 758 } |
| 759 |
| 760 void AudioRendererHost::OnPlayEntry(AudioEntry* entry) { |
| 761 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 762 |
| 763 if (!entry) { |
| 764 SendErrorMessage(0); |
| 765 return; |
| 766 } |
| 767 |
| 768 entry->controller()->Play(); |
| 769 audio_log_->OnStarted(0); |
| 770 } |
| 771 |
| 603 void AudioRendererHost::OnPlayStream(int stream_id) { | 772 void AudioRendererHost::OnPlayStream(int stream_id) { |
| 604 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 773 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 605 | 774 |
| 606 AudioEntry* entry = LookupById(stream_id); | 775 AudioEntry* entry = LookupById(stream_id); |
| 607 if (!entry) { | 776 if (!entry) { |
| 608 SendErrorMessage(stream_id); | 777 SendErrorMessage(stream_id); |
| 609 return; | 778 return; |
| 610 } | 779 } |
| 611 | 780 |
| 612 entry->controller()->Play(); | 781 entry->controller()->Play(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 641 entry->controller()->SetVolume(volume); | 810 entry->controller()->SetVolume(volume); |
| 642 audio_log_->OnSetVolume(stream_id, volume); | 811 audio_log_->OnSetVolume(stream_id, volume); |
| 643 } | 812 } |
| 644 | 813 |
| 645 void AudioRendererHost::SendErrorMessage(int stream_id) { | 814 void AudioRendererHost::SendErrorMessage(int stream_id) { |
| 646 Send(new AudioMsg_NotifyStreamStateChanged( | 815 Send(new AudioMsg_NotifyStreamStateChanged( |
| 647 stream_id, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)); | 816 stream_id, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)); |
| 648 } | 817 } |
| 649 | 818 |
| 650 void AudioRendererHost::OnCloseStream(int stream_id) { | 819 void AudioRendererHost::OnCloseStream(int stream_id) { |
| 820 DLOG(WARNING) << "OnCloseStream " << stream_id; |
| 651 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 821 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 652 authorizations_.erase(stream_id); | 822 authorizations_.erase(stream_id); |
| 653 | 823 |
| 654 // Prevent oustanding callbacks from attempting to close/delete the same | 824 // Prevent oustanding callbacks from attempting to close/delete the same |
| 655 // AudioEntry twice. | 825 // AudioEntry twice. |
| 656 AudioEntryMap::iterator i = audio_entries_.find(stream_id); | 826 AudioEntryMap::iterator i = audio_entries_.find(stream_id); |
| 657 if (i == audio_entries_.end()) | 827 if (i == audio_entries_.end()) |
| 658 return; | 828 return; |
| 659 scoped_ptr<AudioEntry> entry(i->second); | 829 scoped_ptr<AudioEntry> entry(i->second); |
| 660 audio_entries_.erase(i); | 830 audio_entries_.erase(i); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 690 // is closed. | 860 // is closed. |
| 691 if (!LookupById(stream_id)) | 861 if (!LookupById(stream_id)) |
| 692 return; | 862 return; |
| 693 | 863 |
| 694 SendErrorMessage(stream_id); | 864 SendErrorMessage(stream_id); |
| 695 | 865 |
| 696 audio_log_->OnError(stream_id); | 866 audio_log_->OnError(stream_id); |
| 697 OnCloseStream(stream_id); | 867 OnCloseStream(stream_id); |
| 698 } | 868 } |
| 699 | 869 |
| 700 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) { | 870 void AudioRendererHost::ReportErrorAndCloseMojo( |
| 871 int stream_id, |
| 872 const mojom::AudioOutput::CreateStreamCallback& callback) { |
| 873 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 874 |
| 875 // Make sure this isn't a stray callback executing after the stream has been |
| 876 // closed, so error notifications aren't sent after clients believe the stream |
| 877 // is closed. |
| 878 if (!LookupById(stream_id)) |
| 879 return; |
| 880 mojo::ScopedSharedBufferHandle shared_buffer_handle = |
| 881 mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle()); |
| 882 |
| 883 mojo::ScopedHandle socket_handle = mojo::ScopedHandle(mojo::Handle()); |
| 884 |
| 885 callback.Run(mojom::AudioOutputStreamPtr(), stream_id, |
| 886 std::move(shared_buffer_handle), std::move(socket_handle)); |
| 887 |
| 888 audio_log_->OnError(stream_id); |
| 889 OnCloseStream(stream_id); |
| 890 } |
| 891 |
| 892 AudioEntry* AudioRendererHost::LookupById(int stream_id) { |
| 701 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 893 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 702 | 894 |
| 703 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); | 895 AudioEntryMap::const_iterator i = audio_entries_.find(stream_id); |
| 704 return i != audio_entries_.end() ? i->second : NULL; | 896 return i != audio_entries_.end() ? i->second : NULL; |
| 705 } | 897 } |
| 706 | 898 |
| 707 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, | 899 void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry, |
| 708 bool is_playing) { | 900 bool is_playing) { |
| 709 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 901 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 710 if (entry->playing() == is_playing) | 902 if (entry->playing() == is_playing) |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 callback.Run(false, device_info); | 1010 callback.Run(false, device_info); |
| 819 } | 1011 } |
| 820 | 1012 |
| 821 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { | 1013 bool AudioRendererHost::IsAuthorizationStarted(int stream_id) { |
| 822 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1014 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 823 const auto& i = authorizations_.find(stream_id); | 1015 const auto& i = authorizations_.find(stream_id); |
| 824 return i != authorizations_.end(); | 1016 return i != authorizations_.end(); |
| 825 } | 1017 } |
| 826 | 1018 |
| 827 } // namespace content | 1019 } // namespace content |
| OLD | NEW |