Chromium Code Reviews| 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_input_renderer_host.h" | 5 #include "content/browser/renderer_host/media/audio_input_renderer_host.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/memory/shared_memory.h" | 8 #include "base/memory/shared_memory.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/numerics/safe_math.h" | 10 #include "base/numerics/safe_math.h" |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 49 // |shared_memory_segment_count| equal lengthed segments. | 49 // |shared_memory_segment_count| equal lengthed segments. |
| 50 base::SharedMemory shared_memory; | 50 base::SharedMemory shared_memory; |
| 51 int shared_memory_segment_count; | 51 int shared_memory_segment_count; |
| 52 | 52 |
| 53 // The synchronous writer to be used by the controller. We have the | 53 // The synchronous writer to be used by the controller. We have the |
| 54 // ownership of the writer. | 54 // ownership of the writer. |
| 55 scoped_ptr<media::AudioInputController::SyncWriter> writer; | 55 scoped_ptr<media::AudioInputController::SyncWriter> writer; |
| 56 | 56 |
| 57 // Set to true after we called Close() for the controller. | 57 // Set to true after we called Close() for the controller. |
| 58 bool pending_close; | 58 bool pending_close; |
| 59 | |
| 60 // If this entry's layout has a keyboard mic channel. | |
| 61 bool has_keyboard_mic_; | |
| 59 }; | 62 }; |
| 60 | 63 |
| 61 AudioInputRendererHost::AudioEntry::AudioEntry() | 64 AudioInputRendererHost::AudioEntry::AudioEntry() |
| 62 : stream_id(0), | 65 : stream_id(0), |
| 63 shared_memory_segment_count(0), | 66 shared_memory_segment_count(0), |
| 64 pending_close(false) { | 67 pending_close(false), |
| 68 has_keyboard_mic_(false) { | |
| 65 } | 69 } |
| 66 | 70 |
| 67 AudioInputRendererHost::AudioEntry::~AudioEntry() {} | 71 AudioInputRendererHost::AudioEntry::~AudioEntry() {} |
| 68 | 72 |
| 69 AudioInputRendererHost::AudioInputRendererHost( | 73 AudioInputRendererHost::AudioInputRendererHost( |
| 70 media::AudioManager* audio_manager, | 74 media::AudioManager* audio_manager, |
| 71 MediaStreamManager* media_stream_manager, | 75 MediaStreamManager* media_stream_manager, |
| 72 AudioMirroringManager* audio_mirroring_manager, | 76 AudioMirroringManager* audio_mirroring_manager, |
| 73 media::UserInputMonitor* user_input_monitor) | 77 media::UserInputMonitor* user_input_monitor) |
| 74 : BrowserMessageFilter(AudioMsgStart), | 78 : BrowserMessageFilter(AudioMsgStart), |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 return handled; | 270 return handled; |
| 267 } | 271 } |
| 268 | 272 |
| 269 void AudioInputRendererHost::OnCreateStream( | 273 void AudioInputRendererHost::OnCreateStream( |
| 270 int stream_id, | 274 int stream_id, |
| 271 int render_view_id, | 275 int render_view_id, |
| 272 int session_id, | 276 int session_id, |
| 273 const AudioInputHostMsg_CreateStream_Config& config) { | 277 const AudioInputHostMsg_CreateStream_Config& config) { |
| 274 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 278 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 275 | 279 |
| 280 #if defined(OS_CHROMEOS) | |
| 281 if (config.params.channel_layout() == | |
| 282 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { | |
| 283 media_stream_manager_->audio_input_device_manager() | |
| 284 ->RegisterKeyboardMicStream( | |
| 285 base::Bind(&AudioInputRendererHost::DoCreateStream, | |
| 286 this, | |
| 287 stream_id, | |
| 288 render_view_id, | |
| 289 session_id, | |
| 290 config)); | |
| 291 } else { | |
| 292 DoCreateStream(stream_id, render_view_id, session_id, config); | |
|
tommi (sloooow) - chröme
2014/09/23 13:47:36
fix indent
Henrik Grunell
2014/09/23 15:00:20
Done.
| |
| 293 } | |
| 294 #else | |
| 295 DoCreateStream(stream_id, render_view_id, session_id, config); | |
| 296 #endif | |
| 297 } | |
| 298 | |
| 299 void AudioInputRendererHost::DoCreateStream( | |
| 300 int stream_id, | |
| 301 int render_view_id, | |
| 302 int session_id, | |
| 303 const AudioInputHostMsg_CreateStream_Config& config) { | |
| 304 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 305 | |
| 276 std::ostringstream oss; | 306 std::ostringstream oss; |
| 277 oss << "[stream_id=" << stream_id << "] " | 307 oss << "[stream_id=" << stream_id << "] " |
| 278 << "AIRH::OnCreateStream(render_view_id=" << render_view_id | 308 << "AIRH::OnCreateStream(render_view_id=" << render_view_id |
| 279 << ", session_id=" << session_id << ")"; | 309 << ", session_id=" << session_id << ")"; |
| 280 DCHECK_GT(render_view_id, 0); | 310 DCHECK_GT(render_view_id, 0); |
| 281 | 311 |
| 282 // media::AudioParameters is validated in the deserializer. | 312 // media::AudioParameters is validated in the deserializer. |
| 283 if (LookupById(stream_id) != NULL) { | 313 if (LookupById(stream_id) != NULL) { |
| 284 SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS); | 314 SendErrorMessage(stream_id, STREAM_ALREADY_EXISTS); |
| 315 MaybeUnregisterKeyboardMicStream(config); | |
| 285 return; | 316 return; |
| 286 } | 317 } |
| 287 | 318 |
| 288 media::AudioParameters audio_params(config.params); | 319 media::AudioParameters audio_params(config.params); |
| 289 if (media_stream_manager_->audio_input_device_manager()-> | 320 if (media_stream_manager_->audio_input_device_manager()-> |
| 290 ShouldUseFakeDevice()) { | 321 ShouldUseFakeDevice()) { |
| 291 audio_params.Reset( | 322 audio_params.Reset( |
| 292 media::AudioParameters::AUDIO_FAKE, | 323 media::AudioParameters::AUDIO_FAKE, |
| 293 config.params.channel_layout(), config.params.channels(), | 324 config.params.channel_layout(), config.params.channels(), |
| 294 config.params.sample_rate(), config.params.bits_per_sample(), | 325 config.params.sample_rate(), config.params.bits_per_sample(), |
| 295 config.params.frames_per_buffer()); | 326 config.params.frames_per_buffer()); |
| 296 } | 327 } |
| 297 | 328 |
| 298 // Check if we have the permission to open the device and which device to use. | 329 // Check if we have the permission to open the device and which device to use. |
| 299 std::string device_name; | 330 std::string device_name; |
| 300 std::string device_id = media::AudioManagerBase::kDefaultDeviceId; | 331 std::string device_id = media::AudioManagerBase::kDefaultDeviceId; |
| 301 if (audio_params.format() != media::AudioParameters::AUDIO_FAKE) { | 332 if (audio_params.format() != media::AudioParameters::AUDIO_FAKE) { |
| 302 const StreamDeviceInfo* info = media_stream_manager_-> | 333 const StreamDeviceInfo* info = media_stream_manager_-> |
| 303 audio_input_device_manager()->GetOpenedDeviceInfoById(session_id); | 334 audio_input_device_manager()->GetOpenedDeviceInfoById(session_id); |
| 304 if (!info) { | 335 if (!info) { |
| 305 SendErrorMessage(stream_id, PERMISSION_DENIED); | 336 SendErrorMessage(stream_id, PERMISSION_DENIED); |
| 306 DLOG(WARNING) << "No permission has been granted to input stream with " | 337 DLOG(WARNING) << "No permission has been granted to input stream with " |
| 307 << "session_id=" << session_id; | 338 << "session_id=" << session_id; |
| 339 MaybeUnregisterKeyboardMicStream(config); | |
| 308 return; | 340 return; |
| 309 } | 341 } |
| 310 | 342 |
| 311 device_id = info->device.id; | 343 device_id = info->device.id; |
| 312 device_name = info->device.name; | 344 device_name = info->device.name; |
| 313 oss << ": device_name=" << device_name; | 345 oss << ": device_name=" << device_name; |
| 314 } | 346 } |
| 315 | 347 |
| 316 // Create a new AudioEntry structure. | 348 // Create a new AudioEntry structure. |
| 317 scoped_ptr<AudioEntry> entry(new AudioEntry()); | 349 scoped_ptr<AudioEntry> entry(new AudioEntry()); |
| 318 | 350 |
| 319 const uint32 segment_size = | 351 const uint32 segment_size = |
| 320 (sizeof(media::AudioInputBufferParameters) + | 352 (sizeof(media::AudioInputBufferParameters) + |
| 321 media::AudioBus::CalculateMemorySize(audio_params)); | 353 media::AudioBus::CalculateMemorySize(audio_params)); |
| 322 entry->shared_memory_segment_count = config.shared_memory_count; | 354 entry->shared_memory_segment_count = config.shared_memory_count; |
| 323 | 355 |
| 324 // Create the shared memory and share it with the renderer process | 356 // Create the shared memory and share it with the renderer process |
| 325 // using a new SyncWriter object. | 357 // using a new SyncWriter object. |
| 326 base::CheckedNumeric<uint32> size = segment_size; | 358 base::CheckedNumeric<uint32> size = segment_size; |
| 327 size *= entry->shared_memory_segment_count; | 359 size *= entry->shared_memory_segment_count; |
| 328 if (!size.IsValid() || | 360 if (!size.IsValid() || |
| 329 !entry->shared_memory.CreateAndMapAnonymous(size.ValueOrDie())) { | 361 !entry->shared_memory.CreateAndMapAnonymous(size.ValueOrDie())) { |
| 330 // If creation of shared memory failed then send an error message. | 362 // If creation of shared memory failed then send an error message. |
| 331 SendErrorMessage(stream_id, SHARED_MEMORY_CREATE_FAILED); | 363 SendErrorMessage(stream_id, SHARED_MEMORY_CREATE_FAILED); |
| 364 MaybeUnregisterKeyboardMicStream(config); | |
| 332 return; | 365 return; |
| 333 } | 366 } |
| 334 | 367 |
| 335 scoped_ptr<AudioInputSyncWriter> writer(new AudioInputSyncWriter( | 368 scoped_ptr<AudioInputSyncWriter> writer(new AudioInputSyncWriter( |
| 336 &entry->shared_memory, entry->shared_memory_segment_count, audio_params)); | 369 &entry->shared_memory, entry->shared_memory_segment_count, audio_params)); |
| 337 | 370 |
| 338 if (!writer->Init()) { | 371 if (!writer->Init()) { |
| 339 SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED); | 372 SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED); |
| 373 MaybeUnregisterKeyboardMicStream(config); | |
| 340 return; | 374 return; |
| 341 } | 375 } |
| 342 | 376 |
| 343 // If we have successfully created the SyncWriter then assign it to the | 377 // If we have successfully created the SyncWriter then assign it to the |
| 344 // entry and construct an AudioInputController. | 378 // entry and construct an AudioInputController. |
| 345 entry->writer.reset(writer.release()); | 379 entry->writer.reset(writer.release()); |
| 346 if (WebContentsCaptureUtil::IsWebContentsDeviceId(device_id)) { | 380 if (WebContentsCaptureUtil::IsWebContentsDeviceId(device_id)) { |
| 347 entry->controller = media::AudioInputController::CreateForStream( | 381 entry->controller = media::AudioInputController::CreateForStream( |
| 348 audio_manager_->GetTaskRunner(), | 382 audio_manager_->GetTaskRunner(), |
| 349 this, | 383 this, |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 362 media::AudioInputController::CreateLowLatency(audio_manager_, | 396 media::AudioInputController::CreateLowLatency(audio_manager_, |
| 363 this, | 397 this, |
| 364 audio_params, | 398 audio_params, |
| 365 device_id, | 399 device_id, |
| 366 entry->writer.get(), | 400 entry->writer.get(), |
| 367 user_input_monitor_); | 401 user_input_monitor_); |
| 368 } | 402 } |
| 369 | 403 |
| 370 if (!entry->controller.get()) { | 404 if (!entry->controller.get()) { |
| 371 SendErrorMessage(stream_id, STREAM_CREATE_ERROR); | 405 SendErrorMessage(stream_id, STREAM_CREATE_ERROR); |
| 406 MaybeUnregisterKeyboardMicStream(config); | |
| 372 return; | 407 return; |
| 373 } | 408 } |
| 374 | 409 |
| 375 // Set the initial AGC state for the audio input stream. Note that, the AGC | 410 // Set the initial AGC state for the audio input stream. Note that, the AGC |
| 376 // is only supported in AUDIO_PCM_LOW_LATENCY mode. | 411 // is only supported in AUDIO_PCM_LOW_LATENCY mode. |
| 377 if (config.params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY) { | 412 if (config.params.format() == media::AudioParameters::AUDIO_PCM_LOW_LATENCY) { |
| 378 entry->controller->SetAutomaticGainControl(config.automatic_gain_control); | 413 entry->controller->SetAutomaticGainControl(config.automatic_gain_control); |
| 379 oss << ", AGC=" << config.automatic_gain_control; | 414 oss << ", AGC=" << config.automatic_gain_control; |
| 380 } | 415 } |
| 381 | 416 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 this, entry)); | 489 this, entry)); |
| 455 entry->pending_close = true; | 490 entry->pending_close = true; |
| 456 audio_log_->OnClosed(entry->stream_id); | 491 audio_log_->OnClosed(entry->stream_id); |
| 457 } | 492 } |
| 458 } | 493 } |
| 459 | 494 |
| 460 void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) { | 495 void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) { |
| 461 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 496 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 462 LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true); | 497 LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true); |
| 463 | 498 |
| 499 #if defined(OS_CHROMEOS) | |
| 500 if (entry->has_keyboard_mic_) { | |
| 501 media_stream_manager_->audio_input_device_manager() | |
| 502 ->UnregisterKeyboardMicStream(); | |
| 503 } | |
| 504 #endif | |
| 505 | |
| 464 // Delete the entry when this method goes out of scope. | 506 // Delete the entry when this method goes out of scope. |
| 465 scoped_ptr<AudioEntry> entry_deleter(entry); | 507 scoped_ptr<AudioEntry> entry_deleter(entry); |
| 466 | 508 |
| 467 // Erase the entry from the map. | 509 // Erase the entry from the map. |
| 468 audio_entries_.erase(entry->stream_id); | 510 audio_entries_.erase(entry->stream_id); |
| 469 } | 511 } |
| 470 | 512 |
| 471 void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry, | 513 void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry, |
| 472 ErrorCode error_code) { | 514 ErrorCode error_code) { |
| 473 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 515 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 495 // Iterate the map of entries. | 537 // Iterate the map of entries. |
| 496 // TODO(hclam): Implement a faster look up method. | 538 // TODO(hclam): Implement a faster look up method. |
| 497 for (AudioEntryMap::iterator i = audio_entries_.begin(); | 539 for (AudioEntryMap::iterator i = audio_entries_.begin(); |
| 498 i != audio_entries_.end(); ++i) { | 540 i != audio_entries_.end(); ++i) { |
| 499 if (controller == i->second->controller.get()) | 541 if (controller == i->second->controller.get()) |
| 500 return i->second; | 542 return i->second; |
| 501 } | 543 } |
| 502 return NULL; | 544 return NULL; |
| 503 } | 545 } |
| 504 | 546 |
| 547 void AudioInputRendererHost::MaybeUnregisterKeyboardMicStream( | |
| 548 const AudioInputHostMsg_CreateStream_Config& config) { | |
| 549 #if defined(OS_CHROMEOS) | |
| 550 if (config.params.channel_layout() == | |
| 551 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { | |
|
tommi (sloooow) - chröme
2014/09/23 13:47:36
were there any plans to support mono+keyboard mic?
Henrik Grunell
2014/09/23 15:00:20
No.
| |
| 552 media_stream_manager_->audio_input_device_manager() | |
| 553 ->UnregisterKeyboardMicStream(); | |
| 554 } | |
| 555 #endif | |
| 556 } | |
| 557 | |
| 505 } // namespace content | 558 } // namespace content |
| OLD | NEW |