Add git cl format presubmit warning for extension and apps.
[chromium-blink-merge.git] / media / audio / audio_output_dispatcher_impl.cc
blobd2e1d1c6c66f6bf35e7dae2e73e03a14e62d8888
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
3 // found in the LICENSE file.
5 #include "media/audio/audio_output_dispatcher_impl.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/compiler_specific.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/time/time.h"
13 #include "media/audio/audio_io.h"
14 #include "media/audio/audio_output_proxy.h"
16 namespace media {
18 AudioOutputDispatcherImpl::AudioOutputDispatcherImpl(
19 AudioManager* audio_manager,
20 const AudioParameters& params,
21 const std::string& output_device_id,
22 const std::string& input_device_id,
23 const base::TimeDelta& close_delay)
24 : AudioOutputDispatcher(audio_manager,
25 params,
26 output_device_id,
27 input_device_id),
28 idle_proxies_(0),
29 close_timer_(FROM_HERE,
30 close_delay,
31 this,
32 &AudioOutputDispatcherImpl::CloseAllIdleStreams),
33 audio_log_(
34 audio_manager->CreateAudioLog(AudioLogFactory::AUDIO_OUTPUT_STREAM)),
35 audio_stream_id_(0) {}
37 AudioOutputDispatcherImpl::~AudioOutputDispatcherImpl() {
38 DCHECK_EQ(idle_proxies_, 0u);
39 DCHECK(proxy_to_physical_map_.empty());
40 DCHECK(idle_streams_.empty());
43 bool AudioOutputDispatcherImpl::OpenStream() {
44 DCHECK(task_runner_->BelongsToCurrentThread());
46 // Ensure that there is at least one open stream.
47 if (idle_streams_.empty() && !CreateAndOpenStream())
48 return false;
50 ++idle_proxies_;
51 close_timer_.Reset();
52 return true;
55 bool AudioOutputDispatcherImpl::StartStream(
56 AudioOutputStream::AudioSourceCallback* callback,
57 AudioOutputProxy* stream_proxy) {
58 DCHECK(task_runner_->BelongsToCurrentThread());
59 DCHECK(proxy_to_physical_map_.find(stream_proxy) ==
60 proxy_to_physical_map_.end());
62 if (idle_streams_.empty() && !CreateAndOpenStream())
63 return false;
65 AudioOutputStream* physical_stream = idle_streams_.back();
66 idle_streams_.pop_back();
68 DCHECK_GT(idle_proxies_, 0u);
69 --idle_proxies_;
71 double volume = 0;
72 stream_proxy->GetVolume(&volume);
73 physical_stream->SetVolume(volume);
74 const int stream_id = audio_stream_ids_[physical_stream];
75 audio_log_->OnSetVolume(stream_id, volume);
76 physical_stream->Start(callback);
77 audio_log_->OnStarted(stream_id);
78 proxy_to_physical_map_[stream_proxy] = physical_stream;
80 close_timer_.Reset();
81 return true;
84 void AudioOutputDispatcherImpl::StopStream(AudioOutputProxy* stream_proxy) {
85 DCHECK(task_runner_->BelongsToCurrentThread());
87 AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy);
88 DCHECK(it != proxy_to_physical_map_.end());
89 AudioOutputStream* physical_stream = it->second;
90 proxy_to_physical_map_.erase(it);
92 physical_stream->Stop();
93 audio_log_->OnStopped(audio_stream_ids_[physical_stream]);
94 ++idle_proxies_;
95 idle_streams_.push_back(physical_stream);
97 close_timer_.Reset();
100 void AudioOutputDispatcherImpl::StreamVolumeSet(AudioOutputProxy* stream_proxy,
101 double volume) {
102 DCHECK(task_runner_->BelongsToCurrentThread());
103 AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy);
104 if (it != proxy_to_physical_map_.end()) {
105 AudioOutputStream* physical_stream = it->second;
106 physical_stream->SetVolume(volume);
107 audio_log_->OnSetVolume(audio_stream_ids_[physical_stream], volume);
111 void AudioOutputDispatcherImpl::CloseStream(AudioOutputProxy* stream_proxy) {
112 DCHECK(task_runner_->BelongsToCurrentThread());
114 DCHECK_GT(idle_proxies_, 0u);
115 --idle_proxies_;
117 // Leave at least a single stream running until the close timer fires to help
118 // cycle time when streams are opened and closed repeatedly.
119 CloseIdleStreams(std::max(idle_proxies_, static_cast<size_t>(1)));
120 close_timer_.Reset();
123 void AudioOutputDispatcherImpl::Shutdown() {
124 DCHECK(task_runner_->BelongsToCurrentThread());
126 // Close all idle streams immediately. The |close_timer_| will handle
127 // invalidating any outstanding tasks upon its destruction.
128 CloseAllIdleStreams();
131 bool AudioOutputDispatcherImpl::CreateAndOpenStream() {
132 DCHECK(task_runner_->BelongsToCurrentThread());
133 AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(
134 params_, output_device_id_, input_device_id_);
135 if (!stream)
136 return false;
138 if (!stream->Open()) {
139 stream->Close();
140 return false;
143 const int stream_id = audio_stream_id_++;
144 audio_stream_ids_[stream] = stream_id;
145 audio_log_->OnCreated(
146 stream_id, params_, input_device_id_, output_device_id_);
148 idle_streams_.push_back(stream);
149 return true;
152 void AudioOutputDispatcherImpl::CloseAllIdleStreams() {
153 DCHECK(task_runner_->BelongsToCurrentThread());
154 CloseIdleStreams(0);
157 void AudioOutputDispatcherImpl::CloseIdleStreams(size_t keep_alive) {
158 DCHECK(task_runner_->BelongsToCurrentThread());
159 if (idle_streams_.size() <= keep_alive)
160 return;
161 for (size_t i = keep_alive; i < idle_streams_.size(); ++i) {
162 AudioOutputStream* stream = idle_streams_[i];
163 stream->Close();
165 AudioStreamIDMap::iterator it = audio_stream_ids_.find(stream);
166 DCHECK(it != audio_stream_ids_.end());
167 audio_log_->OnClosed(it->second);
168 audio_stream_ids_.erase(it);
170 idle_streams_.erase(idle_streams_.begin() + keep_alive, idle_streams_.end());
173 void AudioOutputDispatcherImpl::CloseStreamsForWedgeFix() {
174 DCHECK(task_runner_->BelongsToCurrentThread());
175 CloseAllIdleStreams();
178 void AudioOutputDispatcherImpl::RestartStreamsForWedgeFix() {
179 DCHECK(task_runner_->BelongsToCurrentThread());
181 // Should only be called when the dispatcher is used with fake streams which
182 // don't need to be shutdown or restarted.
183 CHECK_EQ(params_.format(), AudioParameters::AUDIO_FAKE);
186 } // namespace media