| 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 <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 void LogMessage(int stream_id, const std::string& msg, bool add_prefix) { | 44 void LogMessage(int stream_id, const std::string& msg, bool add_prefix) { |
| 45 std::ostringstream oss; | 45 std::ostringstream oss; |
| 46 oss << "[stream_id=" << stream_id << "] "; | 46 oss << "[stream_id=" << stream_id << "] "; |
| 47 if (add_prefix) | 47 if (add_prefix) |
| 48 oss << "AIRH::"; | 48 oss << "AIRH::"; |
| 49 oss << msg; | 49 oss << msg; |
| 50 content::MediaStreamManager::SendMessageToNativeLog(oss.str()); | 50 content::MediaStreamManager::SendMessageToNativeLog(oss.str()); |
| 51 DVLOG(1) << oss.str(); | 51 DVLOG(1) << oss.str(); |
| 52 } | 52 } |
| 53 | 53 |
| 54 #ifdef ENABLE_WEBRTC | |
| 55 base::File CreateDebugRecordingFile(base::FilePath file_path) { | |
| 56 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
| 57 base::File recording_file( | |
| 58 file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); | |
| 59 PLOG_IF(ERROR, !recording_file.IsValid()) | |
| 60 << "Could not open debug recording file, error=" | |
| 61 << recording_file.error_details(); | |
| 62 return recording_file; | |
| 63 } | |
| 64 | |
| 65 void CloseFile(base::File file) { | |
| 66 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
| 67 // |file| must be closed and destroyed on FILE thread. | |
| 68 } | |
| 69 | |
| 70 void DeleteInputDebugWriterOnFileThread( | |
| 71 std::unique_ptr<AudioInputDebugWriter> writer) { | |
| 72 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
| 73 // |writer| must be closed and destroyed on FILE thread. | |
| 74 } | |
| 75 #endif // ENABLE_WEBRTC | |
| 76 | |
| 77 } // namespace | 54 } // namespace |
| 78 | 55 |
| 79 struct AudioInputRendererHost::AudioEntry { | 56 struct AudioInputRendererHost::AudioEntry { |
| 80 AudioEntry(); | 57 AudioEntry(); |
| 81 ~AudioEntry(); | 58 ~AudioEntry(); |
| 82 | 59 |
| 83 // The AudioInputController that manages the audio input stream. | 60 // The AudioInputController that manages the audio input stream. |
| 84 scoped_refptr<media::AudioInputController> controller; | 61 scoped_refptr<media::AudioInputController> controller; |
| 85 | 62 |
| 86 // The audio input stream ID in the RenderFrame. | 63 // The audio input stream ID in the RenderFrame. |
| 87 int stream_id; | 64 int stream_id; |
| 88 | 65 |
| 89 // Shared memory for transmission of the audio data. It has | 66 // Shared memory for transmission of the audio data. It has |
| 90 // |shared_memory_segment_count| equal lengthed segments. | 67 // |shared_memory_segment_count| equal lengthed segments. |
| 91 base::SharedMemory shared_memory; | 68 base::SharedMemory shared_memory; |
| 92 int shared_memory_segment_count; | 69 int shared_memory_segment_count; |
| 93 | 70 |
| 94 // The synchronous writer to be used by the controller. We have the | 71 // The synchronous writer to be used by the controller. We have the |
| 95 // ownership of the writer. | 72 // ownership of the writer. |
| 96 std::unique_ptr<AudioInputSyncWriter> writer; | 73 std::unique_ptr<AudioInputSyncWriter> writer; |
| 97 | 74 |
| 98 // Must be deleted on the file thread. Must be posted for deletion and nulled | |
| 99 // before the AudioEntry is deleted. | |
| 100 std::unique_ptr<AudioInputDebugWriter> input_debug_writer; | |
| 101 | |
| 102 // Set to true after we called Close() for the controller. | 75 // Set to true after we called Close() for the controller. |
| 103 bool pending_close; | 76 bool pending_close; |
| 104 | 77 |
| 105 // If this entry's layout has a keyboard mic channel. | 78 // If this entry's layout has a keyboard mic channel. |
| 106 bool has_keyboard_mic; | 79 bool has_keyboard_mic; |
| 107 | |
| 108 #ifdef ENABLE_WEBRTC | |
| 109 // Stream audio parameters, used to build wave header for debug recording. | |
| 110 media::AudioParameters audio_params; | |
| 111 #endif // ENABLE_WEBRTC | |
| 112 }; | 80 }; |
| 113 | 81 |
| 114 AudioInputRendererHost::AudioEntry::AudioEntry() | 82 AudioInputRendererHost::AudioEntry::AudioEntry() |
| 115 : stream_id(0), | 83 : stream_id(0), |
| 116 shared_memory_segment_count(0), | 84 shared_memory_segment_count(0), |
| 117 pending_close(false), | 85 pending_close(false), |
| 118 has_keyboard_mic(false) { | 86 has_keyboard_mic(false) { |
| 119 } | 87 } |
| 120 | 88 |
| 121 AudioInputRendererHost::AudioEntry::~AudioEntry() { | 89 AudioInputRendererHost::AudioEntry::~AudioEntry() { |
| 122 DCHECK(!input_debug_writer.get()); | |
| 123 } | 90 } |
| 124 | 91 |
| 125 AudioInputRendererHost::AudioInputRendererHost( | 92 AudioInputRendererHost::AudioInputRendererHost( |
| 126 int render_process_id, | 93 int render_process_id, |
| 127 int32_t renderer_pid, | 94 int32_t renderer_pid, |
| 128 media::AudioManager* audio_manager, | 95 media::AudioManager* audio_manager, |
| 129 MediaStreamManager* media_stream_manager, | 96 MediaStreamManager* media_stream_manager, |
| 130 AudioMirroringManager* audio_mirroring_manager, | 97 AudioMirroringManager* audio_mirroring_manager, |
| 131 media::UserInputMonitor* user_input_monitor) | 98 media::UserInputMonitor* user_input_monitor) |
| 132 : BrowserMessageFilter(AudioMsgStart), | 99 : BrowserMessageFilter(AudioMsgStart), |
| (...skipping 16 matching lines...) Expand all Loading... |
| 149 void AudioInputRendererHost::EnableDebugRecording(const base::FilePath& file) { | 116 void AudioInputRendererHost::EnableDebugRecording(const base::FilePath& file) { |
| 150 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 117 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 151 base::FilePath file_with_extensions = | 118 base::FilePath file_with_extensions = |
| 152 GetDebugRecordingFilePathWithExtensions(file); | 119 GetDebugRecordingFilePathWithExtensions(file); |
| 153 for (const auto& entry : audio_entries_) | 120 for (const auto& entry : audio_entries_) |
| 154 EnableDebugRecordingForId(file_with_extensions, entry.first); | 121 EnableDebugRecordingForId(file_with_extensions, entry.first); |
| 155 } | 122 } |
| 156 | 123 |
| 157 void AudioInputRendererHost::DisableDebugRecording() { | 124 void AudioInputRendererHost::DisableDebugRecording() { |
| 158 for (const auto& entry : audio_entries_) { | 125 for (const auto& entry : audio_entries_) { |
| 159 entry.second->controller->DisableDebugRecording( | 126 entry.second->controller->DisableDebugRecording(); |
| 160 base::Bind(&AudioInputRendererHost::DeleteDebugWriter, | |
| 161 this, | |
| 162 entry.first)); | |
| 163 } | 127 } |
| 164 } | 128 } |
| 165 #endif // ENABLE_WEBRTC | 129 #endif // ENABLE_WEBRTC |
| 166 | 130 |
| 167 void AudioInputRendererHost::OnChannelClosing() { | 131 void AudioInputRendererHost::OnChannelClosing() { |
| 168 // Since the IPC sender is gone, close all requested audio streams. | 132 // Since the IPC sender is gone, close all requested audio streams. |
| 169 DeleteEntries(); | 133 DeleteEntries(); |
| 170 } | 134 } |
| 171 | 135 |
| 172 void AudioInputRendererHost::OnDestruct() const { | 136 void AudioInputRendererHost::OnDestruct() const { |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 std::unique_ptr<AudioInputSyncWriter> writer(new AudioInputSyncWriter( | 381 std::unique_ptr<AudioInputSyncWriter> writer(new AudioInputSyncWriter( |
| 418 entry->shared_memory.memory(), entry->shared_memory.requested_size(), | 382 entry->shared_memory.memory(), entry->shared_memory.requested_size(), |
| 419 entry->shared_memory_segment_count, audio_params)); | 383 entry->shared_memory_segment_count, audio_params)); |
| 420 | 384 |
| 421 if (!writer->Init()) { | 385 if (!writer->Init()) { |
| 422 SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED); | 386 SendErrorMessage(stream_id, SYNC_WRITER_INIT_FAILED); |
| 423 MaybeUnregisterKeyboardMicStream(config); | 387 MaybeUnregisterKeyboardMicStream(config); |
| 424 return; | 388 return; |
| 425 } | 389 } |
| 426 | 390 |
| 391 #if defined(ENABLE_WEBRTC) |
| 392 std::unique_ptr<media::AudioInputWriter> debug_writer( |
| 393 new AudioInputDebugWriter(audio_params)); |
| 394 #else |
| 395 std::unique_ptr<media::AudioInputWriter> debug_writer(nullptr); |
| 396 #endif |
| 397 |
| 427 // If we have successfully created the SyncWriter then assign it to the | 398 // If we have successfully created the SyncWriter then assign it to the |
| 428 // entry and construct an AudioInputController. | 399 // entry and construct an AudioInputController. |
| 429 entry->writer.reset(writer.release()); | 400 entry->writer.reset(writer.release()); |
| 430 if (WebContentsMediaCaptureId::Parse(device_id, nullptr)) { | 401 if (WebContentsMediaCaptureId::Parse(device_id, nullptr)) { |
| 431 // For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker | 402 // For MEDIA_DESKTOP_AUDIO_CAPTURE, the source is selected from picker |
| 432 // window, we do not mute the source audio. | 403 // window, we do not mute the source audio. |
| 433 // For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute | 404 // For MEDIA_TAB_AUDIO_CAPTURE, the probable use case is Cast, we mute |
| 434 // the source audio. | 405 // the source audio. |
| 435 // TODO(qiangchen): Analyze audio constraints to make a duplicating or | 406 // TODO(qiangchen): Analyze audio constraints to make a duplicating or |
| 436 // diverting decision. It would give web developer more flexibility. | 407 // diverting decision. It would give web developer more flexibility. |
| 437 entry->controller = media::AudioInputController::CreateForStream( | 408 entry->controller = media::AudioInputController::CreateForStream( |
| 438 audio_manager_->GetTaskRunner(), this, | 409 audio_manager_->GetTaskRunner(), this, |
| 439 WebContentsAudioInputStream::Create( | 410 WebContentsAudioInputStream::Create( |
| 440 device_id, audio_params, audio_manager_->GetWorkerTaskRunner(), | 411 device_id, audio_params, audio_manager_->GetWorkerTaskRunner(), |
| 441 audio_mirroring_manager_), | 412 audio_mirroring_manager_), |
| 442 entry->writer.get(), user_input_monitor_); | 413 entry->writer.get(), std::move(debug_writer), user_input_monitor_); |
| 443 // Only count for captures from desktop media picker dialog. | 414 // Only count for captures from desktop media picker dialog. |
| 444 if (entry->controller.get() && type == MEDIA_DESKTOP_AUDIO_CAPTURE) | 415 if (entry->controller.get() && type == MEDIA_DESKTOP_AUDIO_CAPTURE) |
| 445 IncrementDesktopCaptureCounter(TAB_AUDIO_CAPTURER_CREATED); | 416 IncrementDesktopCaptureCounter(TAB_AUDIO_CAPTURER_CREATED); |
| 446 } else { | 417 } else { |
| 447 // We call CreateLowLatency regardless of the value of | 418 // We call CreateLowLatency regardless of the value of |
| 448 // |audio_params.format|. Low latency can currently mean different things in | 419 // |audio_params.format|. Low latency can currently mean different things in |
| 449 // different parts of the stack. | 420 // different parts of the stack. |
| 450 // TODO(grunell): Clean up the low latency terminology so that it's less | 421 // TODO(grunell): Clean up the low latency terminology so that it's less |
| 451 // confusing. | 422 // confusing. |
| 452 entry->controller = media::AudioInputController::CreateLowLatency( | 423 entry->controller = media::AudioInputController::CreateLowLatency( |
| 453 audio_manager_, | 424 audio_manager_, this, audio_params, device_id, entry->writer.get(), |
| 454 this, | 425 std::move(debug_writer), user_input_monitor_, |
| 455 audio_params, | |
| 456 device_id, | |
| 457 entry->writer.get(), | |
| 458 user_input_monitor_, | |
| 459 config.automatic_gain_control); | 426 config.automatic_gain_control); |
| 460 oss << ", AGC=" << config.automatic_gain_control; | 427 oss << ", AGC=" << config.automatic_gain_control; |
| 461 | 428 |
| 462 // Only count for captures from desktop media picker dialog and system loop | 429 // Only count for captures from desktop media picker dialog and system loop |
| 463 // back audio. | 430 // back audio. |
| 464 if (entry->controller.get() && type == MEDIA_DESKTOP_AUDIO_CAPTURE && | 431 if (entry->controller.get() && type == MEDIA_DESKTOP_AUDIO_CAPTURE && |
| 465 (device_id == media::AudioDeviceDescription::kLoopbackInputDeviceId || | 432 (device_id == media::AudioDeviceDescription::kLoopbackInputDeviceId || |
| 466 device_id == | 433 device_id == |
| 467 media::AudioDeviceDescription::kLoopbackWithMuteDeviceId)) { | 434 media::AudioDeviceDescription::kLoopbackWithMuteDeviceId)) { |
| 468 IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED); | 435 IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED); |
| 469 } | 436 } |
| 470 } | 437 } |
| 471 | 438 |
| 472 if (!entry->controller.get()) { | 439 if (!entry->controller.get()) { |
| 473 SendErrorMessage(stream_id, STREAM_CREATE_ERROR); | 440 SendErrorMessage(stream_id, STREAM_CREATE_ERROR); |
| 474 MaybeUnregisterKeyboardMicStream(config); | 441 MaybeUnregisterKeyboardMicStream(config); |
| 475 return; | 442 return; |
| 476 } | 443 } |
| 477 | 444 |
| 478 #if defined(OS_CHROMEOS) | 445 #if defined(OS_CHROMEOS) |
| 479 if (config.params.channel_layout() == | 446 if (config.params.channel_layout() == |
| 480 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { | 447 media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC) { |
| 481 entry->has_keyboard_mic = true; | 448 entry->has_keyboard_mic = true; |
| 482 } | 449 } |
| 483 #endif | 450 #endif |
| 484 | 451 |
| 485 #if defined(ENABLE_WEBRTC) | |
| 486 entry->audio_params = audio_params; | |
| 487 #endif // ENABLE_WEBRTC | |
| 488 | |
| 489 MediaStreamManager::SendMessageToNativeLog(oss.str()); | 452 MediaStreamManager::SendMessageToNativeLog(oss.str()); |
| 490 DVLOG(1) << oss.str(); | 453 DVLOG(1) << oss.str(); |
| 491 | 454 |
| 492 // Since the controller was created successfully, create an entry and add it | 455 // Since the controller was created successfully, create an entry and add it |
| 493 // to the map. | 456 // to the map. |
| 494 entry->stream_id = stream_id; | 457 entry->stream_id = stream_id; |
| 495 audio_entries_.insert(std::make_pair(stream_id, entry.release())); | 458 audio_entries_.insert(std::make_pair(stream_id, entry.release())); |
| 496 audio_log_->OnCreated(stream_id, audio_params, device_id); | 459 audio_log_->OnCreated(stream_id, audio_params, device_id); |
| 497 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( | 460 MediaInternals::GetInstance()->SetWebContentsTitleForAudioLogEntry( |
| 498 stream_id, render_process_id_, render_frame_id, audio_log_.get()); | 461 stream_id, render_process_id_, render_frame_id, audio_log_.get()); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 543 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 581 LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true); | 544 LogMessage(entry->stream_id, "DeleteEntry: stream is now closed", true); |
| 582 | 545 |
| 583 #if defined(OS_CHROMEOS) | 546 #if defined(OS_CHROMEOS) |
| 584 if (entry->has_keyboard_mic) { | 547 if (entry->has_keyboard_mic) { |
| 585 media_stream_manager_->audio_input_device_manager() | 548 media_stream_manager_->audio_input_device_manager() |
| 586 ->UnregisterKeyboardMicStream(); | 549 ->UnregisterKeyboardMicStream(); |
| 587 } | 550 } |
| 588 #endif | 551 #endif |
| 589 | 552 |
| 590 #if defined(ENABLE_WEBRTC) | |
| 591 if (entry->input_debug_writer.get()) { | |
| 592 BrowserThread::PostTask( | |
| 593 BrowserThread::FILE, FROM_HERE, | |
| 594 base::Bind(&DeleteInputDebugWriterOnFileThread, | |
| 595 base::Passed(std::move(entry->input_debug_writer)))); | |
| 596 } | |
| 597 #endif | |
| 598 | |
| 599 // Delete the entry when this method goes out of scope. | 553 // Delete the entry when this method goes out of scope. |
| 600 std::unique_ptr<AudioEntry> entry_deleter(entry); | 554 std::unique_ptr<AudioEntry> entry_deleter(entry); |
| 601 | 555 |
| 602 // Erase the entry from the map. | 556 // Erase the entry from the map. |
| 603 audio_entries_.erase(entry->stream_id); | 557 audio_entries_.erase(entry->stream_id); |
| 604 } | 558 } |
| 605 | 559 |
| 606 void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry, | 560 void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry, |
| 607 ErrorCode error_code) { | 561 ErrorCode error_code) { |
| 608 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 562 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 #define IntToStringType base::IntToString | 625 #define IntToStringType base::IntToString |
| 672 #endif | 626 #endif |
| 673 | 627 |
| 674 base::FilePath AudioInputRendererHost::GetDebugRecordingFilePathWithExtensions( | 628 base::FilePath AudioInputRendererHost::GetDebugRecordingFilePathWithExtensions( |
| 675 const base::FilePath& file) { | 629 const base::FilePath& file) { |
| 676 return file.AddExtension(IntToStringType(renderer_pid_)) | 630 return file.AddExtension(IntToStringType(renderer_pid_)) |
| 677 .AddExtension(kDebugRecordingFileNameAddition); | 631 .AddExtension(kDebugRecordingFileNameAddition); |
| 678 } | 632 } |
| 679 | 633 |
| 680 void AudioInputRendererHost::EnableDebugRecordingForId( | 634 void AudioInputRendererHost::EnableDebugRecordingForId( |
| 681 const base::FilePath& file, | 635 const base::FilePath& file_name, |
| 682 int stream_id) { | 636 int stream_id) { |
| 683 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 637 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 684 BrowserThread::PostTaskAndReplyWithResult( | 638 AudioEntry* entry = LookupById(stream_id); |
| 685 BrowserThread::FILE, | 639 if (!entry) |
| 686 FROM_HERE, | 640 return; |
| 687 base::Bind( | 641 entry->controller->EnableDebugRecording( |
| 688 &CreateDebugRecordingFile, | 642 file_name.AddExtension(IntToStringType(stream_id)) |
| 689 file.AddExtension(IntToStringType(stream_id)) | 643 .AddExtension(kDebugRecordingFileNameExtension)); |
| 690 .AddExtension(kDebugRecordingFileNameExtension)), | |
| 691 base::Bind( | |
| 692 &AudioInputRendererHost::DoEnableDebugRecording, | |
| 693 weak_factory_.GetWeakPtr(), | |
| 694 stream_id)); | |
| 695 } | 644 } |
| 696 | 645 |
| 697 #undef IntToStringType | 646 #undef IntToStringType |
| 698 | 647 |
| 699 void AudioInputRendererHost::DoEnableDebugRecording( | |
| 700 int stream_id, | |
| 701 base::File file) { | |
| 702 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 703 if (!file.IsValid()) | |
| 704 return; | |
| 705 AudioEntry* entry = LookupById(stream_id); | |
| 706 if (!entry) { | |
| 707 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 708 base::Bind(&CloseFile, Passed(std::move(file)))); | |
| 709 return; | |
| 710 } | |
| 711 entry->input_debug_writer.reset( | |
| 712 new AudioInputDebugWriter(std::move(file), entry->audio_params)); | |
| 713 entry->controller->EnableDebugRecording(entry->input_debug_writer.get()); | |
| 714 } | |
| 715 | |
| 716 void AudioInputRendererHost::DeleteDebugWriter(int stream_id) { | |
| 717 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 718 AudioEntry* entry = LookupById(stream_id); | |
| 719 if (!entry) { | |
| 720 // This happens if DisableDebugRecording is called right after | |
| 721 // DeleteEntries. | |
| 722 return; | |
| 723 } | |
| 724 | |
| 725 if (entry->input_debug_writer.get()) { | |
| 726 BrowserThread::PostTask( | |
| 727 BrowserThread::FILE, FROM_HERE, | |
| 728 base::Bind(&DeleteInputDebugWriterOnFileThread, | |
| 729 base::Passed(std::move(entry->input_debug_writer)))); | |
| 730 } | |
| 731 } | |
| 732 #endif // defined(ENABLE_WEBRTC) | 648 #endif // defined(ENABLE_WEBRTC) |
| 733 | 649 |
| 734 } // namespace content | 650 } // namespace content |
| OLD | NEW |