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( |
| 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 |