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 "media/audio/audio_manager_base.h" | 5 #include "media/audio/audio_manager_base.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
71 dispatcher_->output_device_id == dispatcher_in->output_device_id); | 71 dispatcher_->output_device_id == dispatcher_in->output_device_id); |
72 } | 72 } |
73 | 73 |
74 private: | 74 private: |
75 const DispatcherParams* dispatcher_; | 75 const DispatcherParams* dispatcher_; |
76 }; | 76 }; |
77 | 77 |
78 AudioManagerBase::AudioManagerBase( | 78 AudioManagerBase::AudioManagerBase( |
79 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 79 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
80 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, | 80 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, |
81 AudioLogFactory* audio_log_factory) | 81 AudioLogFactory* audio_log_factory, |
82 CreateAudioFileWriterCallback create_audio_file_writer_callback) | |
82 : AudioManager(std::move(task_runner), std::move(worker_task_runner)), | 83 : AudioManager(std::move(task_runner), std::move(worker_task_runner)), |
83 max_num_output_streams_(kDefaultMaxOutputStreams), | 84 max_num_output_streams_(kDefaultMaxOutputStreams), |
84 max_num_input_streams_(kDefaultMaxInputStreams), | 85 max_num_input_streams_(kDefaultMaxInputStreams), |
85 num_output_streams_(0), | |
86 // TODO(dalecurtis): Switch this to an base::ObserverListThreadSafe, so we | 86 // TODO(dalecurtis): Switch this to an base::ObserverListThreadSafe, so we |
87 // don't | 87 // don't block the UI thread when swapping devices. |
88 // block the UI thread when swapping devices. | |
89 output_listeners_( | 88 output_listeners_( |
90 base::ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY), | 89 base::ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY), |
91 audio_log_factory_(audio_log_factory) {} | 90 audio_log_factory_(audio_log_factory), |
91 create_audio_file_writer_callback_( | |
92 std::move(create_audio_file_writer_callback)), | |
93 next_filename_id_(1) { | |
94 CHECK(!create_audio_file_writer_callback_.Equals( | |
Max Morin
2017/01/20 07:49:09
is it enough with CHECK(create_audio_file_writer_c
Henrik Grunell
2017/01/20 10:38:56
No, it can still be "empty".
Henrik Grunell
2017/01/25 11:50:49
Oh, I missed the base class. Changed.
| |
95 CreateAudioFileWriterCallback())); | |
96 } | |
92 | 97 |
93 AudioManagerBase::~AudioManagerBase() { | 98 AudioManagerBase::~AudioManagerBase() { |
94 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 99 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
95 | 100 |
96 // All the output streams should have been deleted. | 101 // All the output and input streams should have been deleted. |
97 CHECK_EQ(0, num_output_streams_); | 102 CHECK(output_streams_.empty()); |
98 // All the input streams should have been deleted. | |
99 CHECK(input_streams_.empty()); | 103 CHECK(input_streams_.empty()); |
100 } | 104 } |
101 | 105 |
102 base::string16 AudioManagerBase::GetAudioInputDeviceModel() { | 106 base::string16 AudioManagerBase::GetAudioInputDeviceModel() { |
103 return base::string16(); | 107 return base::string16(); |
104 } | 108 } |
105 | 109 |
106 void AudioManagerBase::GetAudioInputDeviceDescriptions( | 110 void AudioManagerBase::GetAudioInputDeviceDescriptions( |
107 AudioDeviceDescriptions* device_descriptions) { | 111 AudioDeviceDescriptions* device_descriptions) { |
108 CHECK(GetTaskRunner()->BelongsToCurrentThread()); | 112 CHECK(GetTaskRunner()->BelongsToCurrentThread()); |
(...skipping 19 matching lines...) Expand all Loading... | |
128 } | 132 } |
129 | 133 |
130 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( | 134 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream( |
131 const AudioParameters& params, | 135 const AudioParameters& params, |
132 const std::string& device_id, | 136 const std::string& device_id, |
133 const LogCallback& log_callback) { | 137 const LogCallback& log_callback) { |
134 CHECK(GetTaskRunner()->BelongsToCurrentThread()); | 138 CHECK(GetTaskRunner()->BelongsToCurrentThread()); |
135 | 139 |
136 if (!params.IsValid()) { | 140 if (!params.IsValid()) { |
137 DLOG(ERROR) << "Audio parameters are invalid"; | 141 DLOG(ERROR) << "Audio parameters are invalid"; |
138 return NULL; | 142 return nullptr; |
139 } | 143 } |
140 | 144 |
141 // Limit the number of audio streams opened. This is to prevent using | 145 // Limit the number of audio streams opened. This is to prevent using |
142 // excessive resources for a large number of audio streams. More | 146 // excessive resources for a large number of audio streams. More |
143 // importantly it prevents instability on certain systems. | 147 // importantly it prevents instability on certain systems. |
144 // See bug: http://crbug.com/30242. | 148 // See bug: http://crbug.com/30242. |
145 if (num_output_streams_ >= max_num_output_streams_) { | 149 if (output_stream_count() >= max_num_output_streams_) { |
146 DLOG(ERROR) << "Number of opened output audio streams " | 150 DLOG(ERROR) << "Number of opened output audio streams " |
147 << num_output_streams_ | 151 << output_stream_count() << " exceed the max allowed number " |
148 << " exceed the max allowed number " | |
149 << max_num_output_streams_; | 152 << max_num_output_streams_; |
150 return NULL; | 153 return nullptr; |
151 } | 154 } |
152 | 155 |
153 AudioOutputStream* stream; | 156 AudioOutputStream* stream; |
154 switch (params.format()) { | 157 switch (params.format()) { |
155 case AudioParameters::AUDIO_PCM_LINEAR: | 158 case AudioParameters::AUDIO_PCM_LINEAR: |
156 DCHECK(AudioDeviceDescription::IsDefaultDevice(device_id)) | 159 DCHECK(AudioDeviceDescription::IsDefaultDevice(device_id)) |
157 << "AUDIO_PCM_LINEAR supports only the default device."; | 160 << "AUDIO_PCM_LINEAR supports only the default device."; |
158 stream = MakeLinearOutputStream(params, log_callback); | 161 stream = MakeLinearOutputStream(params, log_callback); |
159 break; | 162 break; |
160 case AudioParameters::AUDIO_PCM_LOW_LATENCY: | 163 case AudioParameters::AUDIO_PCM_LOW_LATENCY: |
161 stream = MakeLowLatencyOutputStream(params, device_id, log_callback); | 164 stream = MakeLowLatencyOutputStream(params, device_id, log_callback); |
162 break; | 165 break; |
163 case AudioParameters::AUDIO_BITSTREAM_AC3: | 166 case AudioParameters::AUDIO_BITSTREAM_AC3: |
164 case AudioParameters::AUDIO_BITSTREAM_EAC3: | 167 case AudioParameters::AUDIO_BITSTREAM_EAC3: |
165 // TODO(tsunghung): create passthrough output stream. | 168 // TODO(tsunghung): create passthrough output stream. |
166 NOTREACHED(); | 169 NOTREACHED(); |
167 stream = nullptr; | 170 stream = nullptr; |
168 break; | 171 break; |
169 case AudioParameters::AUDIO_FAKE: | 172 case AudioParameters::AUDIO_FAKE: |
170 stream = FakeAudioOutputStream::MakeFakeStream(this, params); | 173 stream = FakeAudioOutputStream::MakeFakeStream(this, params); |
171 break; | 174 break; |
172 default: | 175 default: |
173 stream = NULL; | 176 stream = nullptr; |
174 break; | 177 break; |
175 } | 178 } |
176 | 179 |
177 if (stream) { | 180 if (stream) { |
178 ++num_output_streams_; | 181 output_streams_.insert(stream); |
182 | |
183 // Debug recording is enabled if the file name is non-empty. If so, also | |
184 // enable it on the new stream. | |
185 if (!debug_recording_base_file_name_.empty()) { | |
186 stream->EnableDebugRecording(GetDebugRecordingFileNameWithExtensions( | |
187 debug_recording_base_file_name_)); | |
188 } | |
179 } | 189 } |
180 | 190 |
181 return stream; | 191 return stream; |
182 } | 192 } |
183 | 193 |
184 AudioInputStream* AudioManagerBase::MakeAudioInputStream( | 194 AudioInputStream* AudioManagerBase::MakeAudioInputStream( |
185 const AudioParameters& params, | 195 const AudioParameters& params, |
186 const std::string& device_id, | 196 const std::string& device_id, |
187 const LogCallback& log_callback) { | 197 const LogCallback& log_callback) { |
188 CHECK(GetTaskRunner()->BelongsToCurrentThread()); | 198 CHECK(GetTaskRunner()->BelongsToCurrentThread()); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
304 AudioDeviceNames* device_names) { | 314 AudioDeviceNames* device_names) { |
305 } | 315 } |
306 | 316 |
307 void AudioManagerBase::GetAudioOutputDeviceNames( | 317 void AudioManagerBase::GetAudioOutputDeviceNames( |
308 AudioDeviceNames* device_names) { | 318 AudioDeviceNames* device_names) { |
309 } | 319 } |
310 | 320 |
311 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) { | 321 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) { |
312 CHECK(GetTaskRunner()->BelongsToCurrentThread()); | 322 CHECK(GetTaskRunner()->BelongsToCurrentThread()); |
313 DCHECK(stream); | 323 DCHECK(stream); |
314 CHECK_GT(num_output_streams_, 0); | 324 stream->DisableDebugRecording(); |
315 // TODO(xians) : Have a clearer destruction path for the AudioOutputStream. | 325 // TODO(grunell): Have a clearer destruction path for the AudioOutputStream. |
316 // For example, pass the ownership to AudioManager so it can delete the | 326 // For example, pass the ownership to AudioManager so it can delete the |
317 // streams. | 327 // streams. |
318 --num_output_streams_; | 328 CHECK_EQ(1u, output_streams_.erase(stream)); |
319 delete stream; | 329 delete stream; |
320 } | 330 } |
321 | 331 |
322 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { | 332 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) { |
323 CHECK(GetTaskRunner()->BelongsToCurrentThread()); | 333 CHECK(GetTaskRunner()->BelongsToCurrentThread()); |
324 DCHECK(stream); | 334 DCHECK(stream); |
325 // TODO(xians) : Have a clearer destruction path for the AudioInputStream. | 335 // TODO(grunell): Have a clearer destruction path for the AudioInputStream. |
326 CHECK_EQ(1u, input_streams_.erase(stream)); | 336 CHECK_EQ(1u, input_streams_.erase(stream)); |
327 delete stream; | 337 delete stream; |
328 } | 338 } |
329 | 339 |
330 void AudioManagerBase::Shutdown() { | 340 void AudioManagerBase::Shutdown() { |
331 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | 341 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); |
332 | 342 |
333 // Close all output streams. | 343 // Close all output streams. |
334 output_dispatchers_.clear(); | 344 output_dispatchers_.clear(); |
335 | 345 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
426 return buffer_size; | 436 return buffer_size; |
427 | 437 |
428 return 0; | 438 return 0; |
429 } | 439 } |
430 | 440 |
431 std::unique_ptr<AudioLog> AudioManagerBase::CreateAudioLog( | 441 std::unique_ptr<AudioLog> AudioManagerBase::CreateAudioLog( |
432 AudioLogFactory::AudioComponent component) { | 442 AudioLogFactory::AudioComponent component) { |
433 return audio_log_factory_->CreateAudioLog(component); | 443 return audio_log_factory_->CreateAudioLog(component); |
434 } | 444 } |
435 | 445 |
446 std::unique_ptr<AudioFileWriter> AudioManagerBase::CreateAudioFileWriter( | |
447 const AudioParameters& params) { | |
448 return create_audio_file_writer_callback_.Run(params); | |
449 } | |
450 | |
451 void AudioManagerBase::EnableOutputDebugRecording( | |
452 const base::FilePath& base_file_name) { | |
453 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | |
454 for (auto it : output_streams_) { | |
455 it->EnableDebugRecording( | |
456 GetDebugRecordingFileNameWithExtensions(base_file_name)); | |
457 } | |
458 debug_recording_base_file_name_ = base_file_name; | |
459 } | |
460 | |
461 void AudioManagerBase::DisableOutputDebugRecording() { | |
462 DCHECK(GetTaskRunner()->BelongsToCurrentThread()); | |
463 for (auto it : output_streams_) | |
464 it->DisableDebugRecording(); | |
465 debug_recording_base_file_name_.clear(); | |
466 } | |
467 | |
468 #if defined(OS_WIN) | |
469 #define IntToStringType base::IntToString16 | |
470 #else | |
471 #define IntToStringType base::IntToString | |
472 #endif | |
473 | |
474 base::FilePath AudioManagerBase::GetDebugRecordingFileNameWithExtensions( | |
475 const base::FilePath& file_name) { | |
476 return file_name.AddExtension("output").AddExtension( | |
477 IntToStringType(next_filename_id_++)); | |
478 } | |
479 | |
436 void AudioManagerBase::SetMaxStreamCountForTesting(int max_input, | 480 void AudioManagerBase::SetMaxStreamCountForTesting(int max_input, |
437 int max_output) { | 481 int max_output) { |
438 max_num_output_streams_ = max_output; | 482 max_num_output_streams_ = max_output; |
439 max_num_input_streams_ = max_input; | 483 max_num_input_streams_ = max_input; |
440 } | 484 } |
441 | 485 |
442 } // namespace media | 486 } // namespace media |
OLD | NEW |