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

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

Issue 2443573003: Factor out AudioOutputDelegate from AudioRendererHost. (Closed)
Patch Set: Simplify. Created 4 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
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_controller.h" 5 #include "media/audio/audio_output_controller.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <limits> 10 #include <limits>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "base/numerics/safe_conversions.h" 14 #include "base/numerics/safe_conversions.h"
15 #include "base/task_runner_util.h" 15 #include "base/task_runner_util.h"
16 #include "base/threading/platform_thread.h" 16 #include "base/threading/platform_thread.h"
17 #include "base/time/time.h" 17 #include "base/time/time.h"
18 #include "base/trace_event/trace_event.h" 18 #include "base/trace_event/trace_event.h"
19 19
20 using base::TimeDelta; 20 using base::TimeDelta;
21 21
22 namespace media { 22 namespace media {
23 23
24 AudioOutputController::AudioOutputController( 24 AudioOutputController::AudioOutputController(
25 AudioManager* audio_manager, 25 AudioManager* audio_manager,
26 EventHandler* handler, 26 EventHandler* handler,
27 const AudioParameters& params, 27 const AudioParameters& params,
28 const std::string& output_device_id, 28 const std::string& output_device_id,
29 SyncReader* sync_reader) 29 std::unique_ptr<SyncReader> sync_reader)
30 : audio_manager_(audio_manager), 30 : audio_manager_(audio_manager),
31 params_(params), 31 params_(params),
32 handler_(handler), 32 handler_(handler),
33 output_device_id_(output_device_id), 33 output_device_id_(output_device_id),
34 stream_(NULL), 34 stream_(NULL),
35 diverting_to_stream_(NULL), 35 diverting_to_stream_(NULL),
36 volume_(1.0), 36 volume_(1.0),
37 state_(kEmpty), 37 state_(kEmpty),
38 sync_reader_(sync_reader), 38 sync_reader_(std::move(sync_reader)),
39 message_loop_(audio_manager->GetTaskRunner()), 39 message_loop_(audio_manager->GetTaskRunner()),
40 power_monitor_( 40 power_monitor_(
41 params.sample_rate(), 41 params.sample_rate(),
42 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)), 42 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)),
43 on_more_io_data_called_(0), 43 on_more_io_data_called_(0),
44 ignore_errors_during_stop_close_(false) { 44 ignore_errors_during_stop_close_(false) {
45 DCHECK(audio_manager); 45 DCHECK(audio_manager);
46 DCHECK(handler_); 46 DCHECK(handler_);
47 DCHECK(sync_reader_); 47 DCHECK(sync_reader_);
48 DCHECK(message_loop_.get()); 48 DCHECK(message_loop_.get());
49 } 49 }
50 50
51 AudioOutputController::~AudioOutputController() { 51 AudioOutputController::~AudioOutputController() {
52 CHECK_EQ(kClosed, state_); 52 CHECK_EQ(kClosed, state_);
53 CHECK_EQ(nullptr, stream_); 53 CHECK_EQ(nullptr, stream_);
54 CHECK(duplication_targets_.empty()); 54 CHECK(duplication_targets_.empty());
55 } 55 }
56 56
57 // static 57 // static
58 scoped_refptr<AudioOutputController> AudioOutputController::Create( 58 scoped_refptr<AudioOutputController> AudioOutputController::Create(
59 AudioManager* audio_manager, 59 AudioManager* audio_manager,
60 EventHandler* event_handler, 60 EventHandler* event_handler,
61 const AudioParameters& params, 61 const AudioParameters& params,
62 const std::string& output_device_id, 62 const std::string& output_device_id,
63 SyncReader* sync_reader) { 63 std::unique_ptr<SyncReader> sync_reader) {
64 CHECK(audio_manager); 64 CHECK(audio_manager);
65 CHECK_EQ(AudioManager::Get(), audio_manager); 65 CHECK_EQ(AudioManager::Get(), audio_manager);
66 DCHECK(sync_reader); 66 DCHECK(sync_reader);
67 67
68 if (!params.IsValid()) 68 if (!params.IsValid())
69 return NULL; 69 return NULL;
70 70
71 scoped_refptr<AudioOutputController> controller(new AudioOutputController( 71 scoped_refptr<AudioOutputController> controller(
72 audio_manager, event_handler, params, output_device_id, sync_reader)); 72 new AudioOutputController(audio_manager, event_handler, params,
73 output_device_id, std::move(sync_reader)));
73 controller->message_loop_->PostTask(FROM_HERE, base::Bind( 74 controller->message_loop_->PostTask(FROM_HERE, base::Bind(
74 &AudioOutputController::DoCreate, controller, false)); 75 &AudioOutputController::DoCreate, controller, false));
75 return controller; 76 return controller;
76 } 77 }
77 78
78 void AudioOutputController::Play() { 79 void AudioOutputController::Play() {
79 CHECK_EQ(AudioManager::Get(), audio_manager_); 80 CHECK_EQ(AudioManager::Get(), audio_manager_);
80 message_loop_->PostTask(FROM_HERE, base::Bind( 81 message_loop_->PostTask(FROM_HERE, base::Bind(
81 &AudioOutputController::DoPlay, this)); 82 &AudioOutputController::DoPlay, this));
82 } 83 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 return; 131 return;
131 132
132 DoStopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener(). 133 DoStopCloseAndClearStream(); // Calls RemoveOutputDeviceChangeListener().
133 DCHECK_EQ(kEmpty, state_); 134 DCHECK_EQ(kEmpty, state_);
134 135
135 stream_ = diverting_to_stream_ ? 136 stream_ = diverting_to_stream_ ?
136 diverting_to_stream_ : 137 diverting_to_stream_ :
137 audio_manager_->MakeAudioOutputStreamProxy(params_, output_device_id_); 138 audio_manager_->MakeAudioOutputStreamProxy(params_, output_device_id_);
138 if (!stream_) { 139 if (!stream_) {
139 state_ = kError; 140 state_ = kError;
140 handler_->OnError(); 141 handler_->OnControllerError();
141 return; 142 return;
142 } 143 }
143 144
144 if (!stream_->Open()) { 145 if (!stream_->Open()) {
145 DoStopCloseAndClearStream(); 146 DoStopCloseAndClearStream();
146 state_ = kError; 147 state_ = kError;
147 handler_->OnError(); 148 handler_->OnControllerError();
148 return; 149 return;
149 } 150 }
150 151
151 // Everything started okay, so re-register for state change callbacks if 152 // Everything started okay, so re-register for state change callbacks if
152 // stream_ was created via AudioManager. 153 // stream_ was created via AudioManager.
153 if (stream_ != diverting_to_stream_) 154 if (stream_ != diverting_to_stream_)
154 audio_manager_->AddOutputDeviceChangeListener(this); 155 audio_manager_->AddOutputDeviceChangeListener(this);
155 156
156 // We have successfully opened the stream. Set the initial volume. 157 // We have successfully opened the stream. Set the initial volume.
157 stream_->SetVolume(volume_); 158 stream_->SetVolume(volume_);
158 159
159 // Finally set the state to kCreated. 160 // Finally set the state to kCreated.
160 state_ = kCreated; 161 state_ = kCreated;
161 162
162 // And then report we have been created if we haven't done so already. 163 // And then report we have been created if we haven't done so already.
163 if (!is_for_device_change) 164 if (!is_for_device_change)
164 handler_->OnCreated(); 165 handler_->OnControllerCreated();
165 } 166 }
166 167
167 void AudioOutputController::DoPlay() { 168 void AudioOutputController::DoPlay() {
168 DCHECK(message_loop_->BelongsToCurrentThread()); 169 DCHECK(message_loop_->BelongsToCurrentThread());
169 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime"); 170 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime");
170 TRACE_EVENT0("audio", "AudioOutputController::DoPlay"); 171 TRACE_EVENT0("audio", "AudioOutputController::DoPlay");
171 172
172 // We can start from created or paused state. 173 // We can start from created or paused state.
173 if (state_ != kCreated && state_ != kPaused) 174 if (state_ != kCreated && state_ != kPaused)
174 return; 175 return;
(...skipping 14 matching lines...) Expand all
189 // it. 190 // it.
190 // 191 //
191 // Timer self-manages its lifetime and WedgeCheck() will only record the UMA 192 // Timer self-manages its lifetime and WedgeCheck() will only record the UMA
192 // statistic if state is still kPlaying. Additional Start() calls will 193 // statistic if state is still kPlaying. Additional Start() calls will
193 // invalidate the previous timer. 194 // invalidate the previous timer.
194 wedge_timer_.reset(new base::OneShotTimer()); 195 wedge_timer_.reset(new base::OneShotTimer());
195 wedge_timer_->Start( 196 wedge_timer_->Start(
196 FROM_HERE, TimeDelta::FromSeconds(5), this, 197 FROM_HERE, TimeDelta::FromSeconds(5), this,
197 &AudioOutputController::WedgeCheck); 198 &AudioOutputController::WedgeCheck);
198 199
199 handler_->OnPlaying(); 200 handler_->OnControllerPlaying();
200 } 201 }
201 202
202 void AudioOutputController::StopStream() { 203 void AudioOutputController::StopStream() {
203 DCHECK(message_loop_->BelongsToCurrentThread()); 204 DCHECK(message_loop_->BelongsToCurrentThread());
204 205
205 if (state_ == kPlaying) { 206 if (state_ == kPlaying) {
206 wedge_timer_.reset(); 207 wedge_timer_.reset();
207 stream_->Stop(); 208 stream_->Stop();
208 209
209 // A stopped stream is silent, and power_montior_.Scan() is no longer being 210 // A stopped stream is silent, and power_montior_.Scan() is no longer being
(...skipping 12 matching lines...) Expand all
222 StopStream(); 223 StopStream();
223 224
224 if (state_ != kPaused) 225 if (state_ != kPaused)
225 return; 226 return;
226 227
227 // Let the renderer know we've stopped. Necessary to let PPAPI clients know 228 // Let the renderer know we've stopped. Necessary to let PPAPI clients know
228 // audio has been shutdown. TODO(dalecurtis): This stinks. PPAPI should have 229 // audio has been shutdown. TODO(dalecurtis): This stinks. PPAPI should have
229 // a better way to know when it should exit PPB_Audio_Shared::Run(). 230 // a better way to know when it should exit PPB_Audio_Shared::Run().
230 sync_reader_->UpdatePendingBytes(std::numeric_limits<uint32_t>::max(), 0); 231 sync_reader_->UpdatePendingBytes(std::numeric_limits<uint32_t>::max(), 0);
231 232
232 handler_->OnPaused(); 233 handler_->OnControllerPaused();
233 } 234 }
234 235
235 void AudioOutputController::DoClose() { 236 void AudioOutputController::DoClose() {
236 DCHECK(message_loop_->BelongsToCurrentThread()); 237 DCHECK(message_loop_->BelongsToCurrentThread());
237 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime"); 238 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime");
238 TRACE_EVENT0("audio", "AudioOutputController::DoClose"); 239 TRACE_EVENT0("audio", "AudioOutputController::DoClose");
239 240
240 if (state_ != kClosed) { 241 if (state_ != kClosed) {
241 DoStopCloseAndClearStream(); 242 DoStopCloseAndClearStream();
242 sync_reader_->Close(); 243 sync_reader_->Close();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 // since it would break the diverted setup. Once diversion is 284 // since it would break the diverted setup. Once diversion is
284 // finished using StopDiverting() the output will switch to the new 285 // finished using StopDiverting() the output will switch to the new
285 // device ID. 286 // device ID.
286 if (stream_ != diverting_to_stream_) 287 if (stream_ != diverting_to_stream_)
287 OnDeviceChange(); 288 OnDeviceChange();
288 } 289 }
289 290
290 void AudioOutputController::DoReportError() { 291 void AudioOutputController::DoReportError() {
291 DCHECK(message_loop_->BelongsToCurrentThread()); 292 DCHECK(message_loop_->BelongsToCurrentThread());
292 if (state_ != kClosed) 293 if (state_ != kClosed)
293 handler_->OnError(); 294 handler_->OnControllerError();
294 } 295 }
295 296
296 int AudioOutputController::OnMoreData(base::TimeDelta delay, 297 int AudioOutputController::OnMoreData(base::TimeDelta delay,
297 base::TimeTicks delay_timestamp, 298 base::TimeTicks delay_timestamp,
298 int prior_frames_skipped, 299 int prior_frames_skipped,
299 AudioBus* dest) { 300 AudioBus* dest) {
300 TRACE_EVENT0("audio", "AudioOutputController::OnMoreData"); 301 TRACE_EVENT0("audio", "AudioOutputController::OnMoreData");
301 302
302 // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck() 303 // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck()
303 // may have already fired if OnMoreData() took an abnormal amount of time). 304 // may have already fired if OnMoreData() took an abnormal amount of time).
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 DCHECK(message_loop_->BelongsToCurrentThread()); 507 DCHECK(message_loop_->BelongsToCurrentThread());
507 508
508 // If we should be playing and we haven't, that's a wedge. 509 // If we should be playing and we haven't, that's a wedge.
509 if (state_ == kPlaying) { 510 if (state_ == kPlaying) {
510 UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess", 511 UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess",
511 base::AtomicRefCountIsOne(&on_more_io_data_called_)); 512 base::AtomicRefCountIsOne(&on_more_io_data_called_));
512 } 513 }
513 } 514 }
514 515
515 } // namespace media 516 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698