Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(136)

Side by Side Diff: content/browser/renderer_host/media/audio_input_renderer_host.cc

Issue 2390153006: Audio input debug recording refactoring to reduce thread hops and simplify object ownership (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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::IsWebContentsDeviceId(device_id)) { 401 if (WebContentsMediaCaptureId::IsWebContentsDeviceId(device_id)) {
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_, type == MEDIA_DESKTOP_AUDIO_CAPTURE), 412 audio_mirroring_manager_, type == MEDIA_DESKTOP_AUDIO_CAPTURE),
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698