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

Side by Side Diff: media/audio/audio_output_dispatcher_impl.cc

Issue 66183002: Replace MessageLoopProxy with SingleThreadTaskRunner for the rest of media/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 1 month 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 | Annotate | Revision Log
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 "media/audio/audio_output_dispatcher_impl.h" 5 #include "media/audio/audio_output_dispatcher_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/message_loop/message_loop.h" 11 #include "base/single_thread_task_runner.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "media/audio/audio_io.h" 13 #include "media/audio/audio_io.h"
14 #include "media/audio/audio_output_proxy.h" 14 #include "media/audio/audio_output_proxy.h"
15 15
16 namespace media { 16 namespace media {
17 17
18 AudioOutputDispatcherImpl::AudioOutputDispatcherImpl( 18 AudioOutputDispatcherImpl::AudioOutputDispatcherImpl(
19 AudioManager* audio_manager, 19 AudioManager* audio_manager,
20 const AudioParameters& params, 20 const AudioParameters& params,
21 const std::string& output_device_id, 21 const std::string& output_device_id,
22 const std::string& input_device_id, 22 const std::string& input_device_id,
23 const base::TimeDelta& close_delay) 23 const base::TimeDelta& close_delay)
24 : AudioOutputDispatcher(audio_manager, params, output_device_id, 24 : AudioOutputDispatcher(audio_manager,
25 input_device_id), 25 params,
26 output_device_id,
27 input_device_id),
26 pause_delay_(base::TimeDelta::FromMicroseconds( 28 pause_delay_(base::TimeDelta::FromMicroseconds(
27 2 * params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond / 29 2 * params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
28 static_cast<float>(params.sample_rate()))), 30 static_cast<float>(params.sample_rate()))),
29 paused_proxies_(0), 31 paused_proxies_(0),
30 weak_this_(this), 32 weak_this_(this),
31 close_timer_(FROM_HERE, 33 close_timer_(FROM_HERE,
32 close_delay, 34 close_delay,
33 this, 35 this,
34 &AudioOutputDispatcherImpl::ClosePendingStreams) { 36 &AudioOutputDispatcherImpl::ClosePendingStreams) {}
35 }
36 37
37 AudioOutputDispatcherImpl::~AudioOutputDispatcherImpl() { 38 AudioOutputDispatcherImpl::~AudioOutputDispatcherImpl() {
38 DCHECK(proxy_to_physical_map_.empty()); 39 DCHECK(proxy_to_physical_map_.empty());
39 DCHECK(idle_streams_.empty()); 40 DCHECK(idle_streams_.empty());
40 DCHECK(pausing_streams_.empty()); 41 DCHECK(pausing_streams_.empty());
41 } 42 }
42 43
43 bool AudioOutputDispatcherImpl::OpenStream() { 44 bool AudioOutputDispatcherImpl::OpenStream() {
44 DCHECK(message_loop_->BelongsToCurrentThread()); 45 DCHECK(task_runner_->BelongsToCurrentThread());
45 46
46 paused_proxies_++; 47 paused_proxies_++;
47 48
48 // Ensure that there is at least one open stream. 49 // Ensure that there is at least one open stream.
49 if (idle_streams_.empty() && !CreateAndOpenStream()) { 50 if (idle_streams_.empty() && !CreateAndOpenStream()) {
50 paused_proxies_--; 51 paused_proxies_--;
51 return false; 52 return false;
52 } 53 }
53 54
54 close_timer_.Reset(); 55 close_timer_.Reset();
55 return true; 56 return true;
56 } 57 }
57 58
58 bool AudioOutputDispatcherImpl::StartStream( 59 bool AudioOutputDispatcherImpl::StartStream(
59 AudioOutputStream::AudioSourceCallback* callback, 60 AudioOutputStream::AudioSourceCallback* callback,
60 AudioOutputProxy* stream_proxy) { 61 AudioOutputProxy* stream_proxy) {
61 DCHECK(message_loop_->BelongsToCurrentThread()); 62 DCHECK(task_runner_->BelongsToCurrentThread());
62 63
63 if (idle_streams_.empty() && !CreateAndOpenStream()) 64 if (idle_streams_.empty() && !CreateAndOpenStream())
64 return false; 65 return false;
65 66
66 AudioOutputStream* physical_stream = idle_streams_.back(); 67 AudioOutputStream* physical_stream = idle_streams_.back();
67 DCHECK(physical_stream); 68 DCHECK(physical_stream);
68 idle_streams_.pop_back(); 69 idle_streams_.pop_back();
69 70
70 DCHECK_GT(paused_proxies_, 0u); 71 DCHECK_GT(paused_proxies_, 0u);
71 --paused_proxies_; 72 --paused_proxies_;
72 73
73 close_timer_.Reset(); 74 close_timer_.Reset();
74 75
75 double volume = 0; 76 double volume = 0;
76 stream_proxy->GetVolume(&volume); 77 stream_proxy->GetVolume(&volume);
77 physical_stream->SetVolume(volume); 78 physical_stream->SetVolume(volume);
78 physical_stream->Start(callback); 79 physical_stream->Start(callback);
79 proxy_to_physical_map_[stream_proxy] = physical_stream; 80 proxy_to_physical_map_[stream_proxy] = physical_stream;
80 return true; 81 return true;
81 } 82 }
82 83
83 void AudioOutputDispatcherImpl::StopStream(AudioOutputProxy* stream_proxy) { 84 void AudioOutputDispatcherImpl::StopStream(AudioOutputProxy* stream_proxy) {
84 DCHECK(message_loop_->BelongsToCurrentThread()); 85 DCHECK(task_runner_->BelongsToCurrentThread());
85 86
86 AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy); 87 AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy);
87 DCHECK(it != proxy_to_physical_map_.end()); 88 DCHECK(it != proxy_to_physical_map_.end());
88 AudioOutputStream* physical_stream = it->second; 89 AudioOutputStream* physical_stream = it->second;
89 proxy_to_physical_map_.erase(it); 90 proxy_to_physical_map_.erase(it);
90 91
91 physical_stream->Stop(); 92 physical_stream->Stop();
92 93
93 ++paused_proxies_; 94 ++paused_proxies_;
94 95
95 pausing_streams_.push_front(physical_stream); 96 pausing_streams_.push_front(physical_stream);
96 97
97 // Don't recycle stream until two buffers worth of time has elapsed. 98 // Don't recycle stream until two buffers worth of time has elapsed.
98 message_loop_->PostDelayedTask( 99 task_runner_->PostDelayedTask(
99 FROM_HERE, 100 FROM_HERE,
100 base::Bind(&AudioOutputDispatcherImpl::StopStreamTask, 101 base::Bind(&AudioOutputDispatcherImpl::StopStreamTask,
101 weak_this_.GetWeakPtr()), 102 weak_this_.GetWeakPtr()),
102 pause_delay_); 103 pause_delay_);
103 } 104 }
104 105
105 void AudioOutputDispatcherImpl::StreamVolumeSet(AudioOutputProxy* stream_proxy, 106 void AudioOutputDispatcherImpl::StreamVolumeSet(AudioOutputProxy* stream_proxy,
106 double volume) { 107 double volume) {
107 DCHECK(message_loop_->BelongsToCurrentThread()); 108 DCHECK(task_runner_->BelongsToCurrentThread());
108 AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy); 109 AudioStreamMap::iterator it = proxy_to_physical_map_.find(stream_proxy);
109 if (it != proxy_to_physical_map_.end()) { 110 if (it != proxy_to_physical_map_.end()) {
110 AudioOutputStream* physical_stream = it->second; 111 AudioOutputStream* physical_stream = it->second;
111 physical_stream->SetVolume(volume); 112 physical_stream->SetVolume(volume);
112 } 113 }
113 } 114 }
114 115
115 void AudioOutputDispatcherImpl::StopStreamTask() { 116 void AudioOutputDispatcherImpl::StopStreamTask() {
116 DCHECK(message_loop_->BelongsToCurrentThread()); 117 DCHECK(task_runner_->BelongsToCurrentThread());
117 118
118 if (pausing_streams_.empty()) 119 if (pausing_streams_.empty())
119 return; 120 return;
120 121
121 AudioOutputStream* stream = pausing_streams_.back(); 122 AudioOutputStream* stream = pausing_streams_.back();
122 pausing_streams_.pop_back(); 123 pausing_streams_.pop_back();
123 idle_streams_.push_back(stream); 124 idle_streams_.push_back(stream);
124 close_timer_.Reset(); 125 close_timer_.Reset();
125 } 126 }
126 127
127 void AudioOutputDispatcherImpl::CloseStream(AudioOutputProxy* stream_proxy) { 128 void AudioOutputDispatcherImpl::CloseStream(AudioOutputProxy* stream_proxy) {
128 DCHECK(message_loop_->BelongsToCurrentThread()); 129 DCHECK(task_runner_->BelongsToCurrentThread());
129 130
130 while (!pausing_streams_.empty()) { 131 while (!pausing_streams_.empty()) {
131 idle_streams_.push_back(pausing_streams_.back()); 132 idle_streams_.push_back(pausing_streams_.back());
132 pausing_streams_.pop_back(); 133 pausing_streams_.pop_back();
133 } 134 }
134 135
135 DCHECK_GT(paused_proxies_, 0u); 136 DCHECK_GT(paused_proxies_, 0u);
136 paused_proxies_--; 137 paused_proxies_--;
137 138
138 while (idle_streams_.size() > paused_proxies_) { 139 while (idle_streams_.size() > paused_proxies_) {
139 idle_streams_.back()->Close(); 140 idle_streams_.back()->Close();
140 idle_streams_.pop_back(); 141 idle_streams_.pop_back();
141 } 142 }
142 } 143 }
143 144
144 void AudioOutputDispatcherImpl::Shutdown() { 145 void AudioOutputDispatcherImpl::Shutdown() {
145 DCHECK(message_loop_->BelongsToCurrentThread()); 146 DCHECK(task_runner_->BelongsToCurrentThread());
146 147
147 // Cancel any pending tasks to close paused streams or create new ones. 148 // Cancel any pending tasks to close paused streams or create new ones.
148 weak_this_.InvalidateWeakPtrs(); 149 weak_this_.InvalidateWeakPtrs();
149 150
150 // No AudioOutputProxy objects should hold a reference to us when we get 151 // No AudioOutputProxy objects should hold a reference to us when we get
151 // to this stage. 152 // to this stage.
152 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference"; 153 DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference";
153 154
154 AudioOutputStreamList::iterator it = idle_streams_.begin(); 155 AudioOutputStreamList::iterator it = idle_streams_.begin();
155 for (; it != idle_streams_.end(); ++it) 156 for (; it != idle_streams_.end(); ++it)
156 (*it)->Close(); 157 (*it)->Close();
157 idle_streams_.clear(); 158 idle_streams_.clear();
158 159
159 it = pausing_streams_.begin(); 160 it = pausing_streams_.begin();
160 for (; it != pausing_streams_.end(); ++it) 161 for (; it != pausing_streams_.end(); ++it)
161 (*it)->Close(); 162 (*it)->Close();
162 pausing_streams_.clear(); 163 pausing_streams_.clear();
163 } 164 }
164 165
165 bool AudioOutputDispatcherImpl::CreateAndOpenStream() { 166 bool AudioOutputDispatcherImpl::CreateAndOpenStream() {
166 DCHECK(message_loop_->BelongsToCurrentThread()); 167 DCHECK(task_runner_->BelongsToCurrentThread());
167 AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream( 168 AudioOutputStream* stream = audio_manager_->MakeAudioOutputStream(
168 params_, output_device_id_, input_device_id_); 169 params_, output_device_id_, input_device_id_);
169 if (!stream) 170 if (!stream)
170 return false; 171 return false;
171 172
172 if (!stream->Open()) { 173 if (!stream->Open()) {
173 stream->Close(); 174 stream->Close();
174 return false; 175 return false;
175 } 176 }
176 idle_streams_.push_back(stream); 177 idle_streams_.push_back(stream);
177 return true; 178 return true;
178 } 179 }
179 180
180 // This method is called by |close_timer_|. 181 // This method is called by |close_timer_|.
181 void AudioOutputDispatcherImpl::ClosePendingStreams() { 182 void AudioOutputDispatcherImpl::ClosePendingStreams() {
182 DCHECK(message_loop_->BelongsToCurrentThread()); 183 DCHECK(task_runner_->BelongsToCurrentThread());
183 while (!idle_streams_.empty()) { 184 while (!idle_streams_.empty()) {
184 idle_streams_.back()->Close(); 185 idle_streams_.back()->Close();
185 idle_streams_.pop_back(); 186 idle_streams_.pop_back();
186 } 187 }
187 } 188 }
188 189
189 } // namespace media 190 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698