| Index: media/audio/audio_manager_base.cc
|
| diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
|
| index 670820dc3a6ad0f446d429cd97b4e3a7484f5c67..8b44ff1c92d185fd3f88fb6a0034ed5ec0cdca50 100644
|
| --- a/media/audio/audio_manager_base.cc
|
| +++ b/media/audio/audio_manager_base.cc
|
| @@ -78,24 +78,28 @@ class AudioManagerBase::CompareByParams {
|
| AudioManagerBase::AudioManagerBase(
|
| scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
| scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
|
| - AudioLogFactory* audio_log_factory)
|
| + AudioLogFactory* audio_log_factory,
|
| + CreateAudioFileWriterCallback create_audio_file_writer_callback)
|
| : AudioManager(std::move(task_runner), std::move(worker_task_runner)),
|
| max_num_output_streams_(kDefaultMaxOutputStreams),
|
| max_num_input_streams_(kDefaultMaxInputStreams),
|
| - num_output_streams_(0),
|
| // TODO(dalecurtis): Switch this to an base::ObserverListThreadSafe, so we
|
| - // don't
|
| - // block the UI thread when swapping devices.
|
| + // don't block the UI thread when swapping devices.
|
| output_listeners_(
|
| base::ObserverList<AudioDeviceListener>::NOTIFY_EXISTING_ONLY),
|
| - audio_log_factory_(audio_log_factory) {}
|
| + audio_log_factory_(audio_log_factory),
|
| + create_audio_file_writer_callback_(
|
| + std::move(create_audio_file_writer_callback)),
|
| + next_filename_id_(1) {
|
| + CHECK(!create_audio_file_writer_callback_.Equals(
|
| + CreateAudioFileWriterCallback()));
|
| +}
|
|
|
| AudioManagerBase::~AudioManagerBase() {
|
| DCHECK(GetTaskRunner()->BelongsToCurrentThread());
|
|
|
| - // All the output streams should have been deleted.
|
| - CHECK_EQ(0, num_output_streams_);
|
| - // All the input streams should have been deleted.
|
| + // All the output and input streams should have been deleted.
|
| + CHECK(output_streams_.empty());
|
| CHECK(input_streams_.empty());
|
| }
|
|
|
| @@ -135,19 +139,18 @@ AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
|
|
|
| if (!params.IsValid()) {
|
| DLOG(ERROR) << "Audio parameters are invalid";
|
| - return NULL;
|
| + return nullptr;
|
| }
|
|
|
| // Limit the number of audio streams opened. This is to prevent using
|
| // excessive resources for a large number of audio streams. More
|
| // importantly it prevents instability on certain systems.
|
| // See bug: http://crbug.com/30242.
|
| - if (num_output_streams_ >= max_num_output_streams_) {
|
| + if (output_stream_count() >= max_num_output_streams_) {
|
| DLOG(ERROR) << "Number of opened output audio streams "
|
| - << num_output_streams_
|
| - << " exceed the max allowed number "
|
| + << output_stream_count() << " exceed the max allowed number "
|
| << max_num_output_streams_;
|
| - return NULL;
|
| + return nullptr;
|
| }
|
|
|
| AudioOutputStream* stream;
|
| @@ -170,12 +173,19 @@ AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
|
| stream = FakeAudioOutputStream::MakeFakeStream(this, params);
|
| break;
|
| default:
|
| - stream = NULL;
|
| + stream = nullptr;
|
| break;
|
| }
|
|
|
| if (stream) {
|
| - ++num_output_streams_;
|
| + output_streams_.insert(stream);
|
| +
|
| + // Debug recording is enabled if the file name is non-empty. If so, also
|
| + // enable it on the new stream.
|
| + if (!debug_recording_base_file_name_.empty()) {
|
| + stream->EnableDebugRecording(GetDebugRecordingFileNameWithExtensions(
|
| + debug_recording_base_file_name_));
|
| + }
|
| }
|
|
|
| return stream;
|
| @@ -311,18 +321,18 @@ void AudioManagerBase::GetAudioOutputDeviceNames(
|
| void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) {
|
| CHECK(GetTaskRunner()->BelongsToCurrentThread());
|
| DCHECK(stream);
|
| - CHECK_GT(num_output_streams_, 0);
|
| - // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
|
| + stream->DisableDebugRecording();
|
| + // TODO(grunell): Have a clearer destruction path for the AudioOutputStream.
|
| // For example, pass the ownership to AudioManager so it can delete the
|
| // streams.
|
| - --num_output_streams_;
|
| + CHECK_EQ(1u, output_streams_.erase(stream));
|
| delete stream;
|
| }
|
|
|
| void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
|
| CHECK(GetTaskRunner()->BelongsToCurrentThread());
|
| DCHECK(stream);
|
| - // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
|
| + // TODO(grunell): Have a clearer destruction path for the AudioInputStream.
|
| CHECK_EQ(1u, input_streams_.erase(stream));
|
| delete stream;
|
| }
|
| @@ -433,6 +443,40 @@ std::unique_ptr<AudioLog> AudioManagerBase::CreateAudioLog(
|
| return audio_log_factory_->CreateAudioLog(component);
|
| }
|
|
|
| +std::unique_ptr<AudioFileWriter> AudioManagerBase::CreateAudioFileWriter(
|
| + const AudioParameters& params) {
|
| + return create_audio_file_writer_callback_.Run(params);
|
| +}
|
| +
|
| +void AudioManagerBase::EnableOutputDebugRecording(
|
| + const base::FilePath& base_file_name) {
|
| + DCHECK(GetTaskRunner()->BelongsToCurrentThread());
|
| + for (auto it : output_streams_) {
|
| + it->EnableDebugRecording(
|
| + GetDebugRecordingFileNameWithExtensions(base_file_name));
|
| + }
|
| + debug_recording_base_file_name_ = base_file_name;
|
| +}
|
| +
|
| +void AudioManagerBase::DisableOutputDebugRecording() {
|
| + DCHECK(GetTaskRunner()->BelongsToCurrentThread());
|
| + for (auto it : output_streams_)
|
| + it->DisableDebugRecording();
|
| + debug_recording_base_file_name_.clear();
|
| +}
|
| +
|
| +#if defined(OS_WIN)
|
| +#define IntToStringType base::IntToString16
|
| +#else
|
| +#define IntToStringType base::IntToString
|
| +#endif
|
| +
|
| +base::FilePath AudioManagerBase::GetDebugRecordingFileNameWithExtensions(
|
| + const base::FilePath& file_name) {
|
| + return file_name.AddExtension("output").AddExtension(
|
| + IntToStringType(next_filename_id_++));
|
| +}
|
| +
|
| void AudioManagerBase::SetMaxStreamCountForTesting(int max_input,
|
| int max_output) {
|
| max_num_output_streams_ = max_output;
|
|
|