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

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

Issue 8818012: Remove the AudioManager singleton. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Set svn eol properties for a couple of files Created 9 years 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
« no previous file with comments | « media/audio/audio_output_controller.h ('k') | media/audio/audio_output_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/threading/platform_thread.h" 10 #include "base/threading/platform_thread.h"
11 #include "base/time.h" 11 #include "base/time.h"
12 12
13 using base::Time; 13 using base::Time;
14 14
15 namespace media { 15 namespace media {
16 16
17 // Signal a pause in low-latency mode. 17 // Signal a pause in low-latency mode.
18 const int AudioOutputController::kPauseMark = -1; 18 const int AudioOutputController::kPauseMark = -1;
19 19
20 // Polling-related constants. 20 // Polling-related constants.
21 const int AudioOutputController::kPollNumAttempts = 3; 21 const int AudioOutputController::kPollNumAttempts = 3;
22 const int AudioOutputController::kPollPauseInMilliseconds = 3; 22 const int AudioOutputController::kPollPauseInMilliseconds = 3;
23 23
24 AudioOutputController::AudioOutputController(EventHandler* handler, 24 AudioOutputController::AudioOutputController(AudioManager* audio_manager,
25 EventHandler* handler,
25 uint32 capacity, 26 uint32 capacity,
26 SyncReader* sync_reader) 27 SyncReader* sync_reader)
27 : handler_(handler), 28 : audio_manager_(audio_manager),
29 handler_(handler),
28 stream_(NULL), 30 stream_(NULL),
29 volume_(1.0), 31 volume_(1.0),
30 state_(kEmpty), 32 state_(kEmpty),
31 buffer_(0, capacity), 33 buffer_(0, capacity),
32 pending_request_(false), 34 pending_request_(false),
33 sync_reader_(sync_reader), 35 sync_reader_(sync_reader),
34 message_loop_(NULL), 36 message_loop_(NULL),
35 number_polling_attempts_left_(0) { 37 number_polling_attempts_left_(0),
38 ALLOW_THIS_IN_INITIALIZER_LIST(weak_this_(this)) {
36 } 39 }
37 40
38 AudioOutputController::~AudioOutputController() { 41 AudioOutputController::~AudioOutputController() {
39 DCHECK_EQ(kClosed, state_); 42 DCHECK_EQ(kClosed, state_);
40 StopCloseAndClearStream(); 43 StopCloseAndClearStream();
41 } 44 }
42 45
43 // static 46 // static
44 scoped_refptr<AudioOutputController> AudioOutputController::Create( 47 scoped_refptr<AudioOutputController> AudioOutputController::Create(
48 AudioManager* audio_manager,
45 EventHandler* event_handler, 49 EventHandler* event_handler,
46 const AudioParameters& params, 50 const AudioParameters& params,
47 uint32 buffer_capacity) { 51 uint32 buffer_capacity) {
48 52 DCHECK(audio_manager);
49 if (!params.IsValid()) 53 if (!params.IsValid() || !audio_manager)
50 return NULL;
51
52 if (!AudioManager::GetAudioManager())
53 return NULL; 54 return NULL;
54 55
55 // Starts the audio controller thread. 56 // Starts the audio controller thread.
56 scoped_refptr<AudioOutputController> controller(new AudioOutputController( 57 scoped_refptr<AudioOutputController> controller(new AudioOutputController(
57 event_handler, buffer_capacity, NULL)); 58 audio_manager, event_handler, buffer_capacity, NULL));
58 59
59 controller->message_loop_ = 60 controller->message_loop_ = audio_manager->GetMessageLoop();
60 AudioManager::GetAudioManager()->GetMessageLoop();
61 controller->message_loop_->PostTask(FROM_HERE, base::Bind( 61 controller->message_loop_->PostTask(FROM_HERE, base::Bind(
62 &AudioOutputController::DoCreate, controller.get(), params)); 62 &AudioOutputController::DoCreate, base::Unretained(controller.get()),
63 params));
63 return controller; 64 return controller;
64 } 65 }
65 66
66 // static 67 // static
67 scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency( 68 scoped_refptr<AudioOutputController> AudioOutputController::CreateLowLatency(
69 AudioManager* audio_manager,
68 EventHandler* event_handler, 70 EventHandler* event_handler,
69 const AudioParameters& params, 71 const AudioParameters& params,
70 SyncReader* sync_reader) { 72 SyncReader* sync_reader) {
71 73 DCHECK(audio_manager);
72 DCHECK(sync_reader); 74 DCHECK(sync_reader);
73 75
74 if (!params.IsValid()) 76 if (!params.IsValid() || !audio_manager)
75 return NULL;
76
77 if (!AudioManager::GetAudioManager())
78 return NULL; 77 return NULL;
79 78
80 // Starts the audio controller thread. 79 // Starts the audio controller thread.
81 scoped_refptr<AudioOutputController> controller(new AudioOutputController( 80 scoped_refptr<AudioOutputController> controller(new AudioOutputController(
82 event_handler, 0, sync_reader)); 81 audio_manager, event_handler, 0, sync_reader));
83 82
84 controller->message_loop_ = 83 controller->message_loop_ = audio_manager->GetMessageLoop();
85 AudioManager::GetAudioManager()->GetMessageLoop();
86 controller->message_loop_->PostTask(FROM_HERE, base::Bind( 84 controller->message_loop_->PostTask(FROM_HERE, base::Bind(
87 &AudioOutputController::DoCreate, controller.get(), params)); 85 &AudioOutputController::DoCreate, base::Unretained(controller.get()),
86 params));
88 return controller; 87 return controller;
89 } 88 }
90 89
91 void AudioOutputController::Play() { 90 void AudioOutputController::Play() {
92 DCHECK(message_loop_); 91 DCHECK(message_loop_);
93 message_loop_->PostTask(FROM_HERE, base::Bind( 92 message_loop_->PostTask(FROM_HERE, base::Bind(
94 &AudioOutputController::DoPlay, this)); 93 &AudioOutputController::DoPlay, base::Unretained(this)));
95 } 94 }
96 95
97 void AudioOutputController::Pause() { 96 void AudioOutputController::Pause() {
98 DCHECK(message_loop_); 97 DCHECK(message_loop_);
99 message_loop_->PostTask(FROM_HERE, base::Bind( 98 message_loop_->PostTask(FROM_HERE, base::Bind(
100 &AudioOutputController::DoPause, this)); 99 &AudioOutputController::DoPause, base::Unretained(this)));
101 } 100 }
102 101
103 void AudioOutputController::Flush() { 102 void AudioOutputController::Flush() {
104 DCHECK(message_loop_); 103 DCHECK(message_loop_);
105 message_loop_->PostTask(FROM_HERE, base::Bind( 104 message_loop_->PostTask(FROM_HERE, base::Bind(
106 &AudioOutputController::DoFlush, this)); 105 &AudioOutputController::DoFlush, base::Unretained(this)));
107 } 106 }
108 107
109 void AudioOutputController::Close(const base::Closure& closed_task) { 108 void AudioOutputController::Close(const base::Closure& closed_task) {
110 DCHECK(!closed_task.is_null()); 109 DCHECK(!closed_task.is_null());
111 DCHECK(message_loop_); 110 DCHECK(message_loop_);
112 message_loop_->PostTask(FROM_HERE, base::Bind( 111 message_loop_->PostTask(FROM_HERE, base::Bind(
113 &AudioOutputController::DoClose, this, closed_task)); 112 &AudioOutputController::DoClose, base::Unretained(this), closed_task));
114 } 113 }
115 114
116 void AudioOutputController::SetVolume(double volume) { 115 void AudioOutputController::SetVolume(double volume) {
117 DCHECK(message_loop_); 116 DCHECK(message_loop_);
118 message_loop_->PostTask(FROM_HERE, base::Bind( 117 message_loop_->PostTask(FROM_HERE, base::Bind(
119 &AudioOutputController::DoSetVolume, this, volume)); 118 &AudioOutputController::DoSetVolume, base::Unretained(this), volume));
120 } 119 }
121 120
122 void AudioOutputController::EnqueueData(const uint8* data, uint32 size) { 121 void AudioOutputController::EnqueueData(const uint8* data, uint32 size) {
123 // Write data to the push source and ask for more data if needed. 122 // Write data to the push source and ask for more data if needed.
124 base::AutoLock auto_lock(lock_); 123 base::AutoLock auto_lock(lock_);
125 pending_request_ = false; 124 pending_request_ = false;
126 // If |size| is set to 0, it indicates that the audio source doesn't have 125 // If |size| is set to 0, it indicates that the audio source doesn't have
127 // more data right now, and so it doesn't make sense to send additional 126 // more data right now, and so it doesn't make sense to send additional
128 // request. 127 // request.
129 if (size) { 128 if (size) {
130 buffer_.Append(data, size); 129 buffer_.Append(data, size);
131 SubmitOnMoreData_Locked(); 130 SubmitOnMoreData_Locked();
132 } 131 }
133 } 132 }
134 133
135 void AudioOutputController::DoCreate(const AudioParameters& params) { 134 void AudioOutputController::DoCreate(const AudioParameters& params) {
136 DCHECK_EQ(message_loop_, MessageLoop::current()); 135 DCHECK_EQ(message_loop_, MessageLoop::current());
137 136
138 // Close() can be called before DoCreate() is executed. 137 // Close() can be called before DoCreate() is executed.
139 if (state_ == kClosed) 138 if (state_ == kClosed)
140 return; 139 return;
141 DCHECK_EQ(kEmpty, state_); 140 DCHECK_EQ(kEmpty, state_);
142 141
143 if (!AudioManager::GetAudioManager())
144 return;
145
146 StopCloseAndClearStream(); 142 StopCloseAndClearStream();
147 stream_ = AudioManager::GetAudioManager()->MakeAudioOutputStreamProxy(params); 143 stream_ = audio_manager_->MakeAudioOutputStreamProxy(params);
148 if (!stream_) { 144 if (!stream_) {
149 // TODO(hclam): Define error types. 145 // TODO(hclam): Define error types.
150 handler_->OnError(this, 0); 146 handler_->OnError(this, 0);
151 return; 147 return;
152 } 148 }
153 149
154 if (!stream_->Open()) { 150 if (!stream_->Open()) {
155 StopCloseAndClearStream(); 151 StopCloseAndClearStream();
156 152
157 // TODO(hclam): Define error types. 153 // TODO(hclam): Define error types.
(...skipping 28 matching lines...) Expand all
186 state_ = kStarting; 182 state_ = kStarting;
187 183
188 // Ask for first packet. 184 // Ask for first packet.
189 sync_reader_->UpdatePendingBytes(0); 185 sync_reader_->UpdatePendingBytes(0);
190 186
191 // Cannot start stream immediately, should give renderer some time 187 // Cannot start stream immediately, should give renderer some time
192 // to deliver data. 188 // to deliver data.
193 number_polling_attempts_left_ = kPollNumAttempts; 189 number_polling_attempts_left_ = kPollNumAttempts;
194 message_loop_->PostDelayedTask( 190 message_loop_->PostDelayedTask(
195 FROM_HERE, 191 FROM_HERE,
196 base::Bind(&AudioOutputController::PollAndStartIfDataReady, this), 192 base::Bind(&AudioOutputController::PollAndStartIfDataReady,
193 weak_this_.GetWeakPtr()),
197 kPollPauseInMilliseconds); 194 kPollPauseInMilliseconds);
198 } else { 195 } else {
199 StartStream(); 196 StartStream();
200 } 197 }
201 } 198 }
202 199
203 void AudioOutputController::PollAndStartIfDataReady() { 200 void AudioOutputController::PollAndStartIfDataReady() {
204 DCHECK_EQ(message_loop_, MessageLoop::current()); 201 DCHECK_EQ(message_loop_, MessageLoop::current());
205 202
206 // Being paranoic: do nothing if state unexpectedly changed. 203 // Being paranoid: do nothing if state unexpectedly changed.
207 if ((state_ != kStarting) && (state_ != kPausedWhenStarting)) 204 if ((state_ != kStarting) && (state_ != kPausedWhenStarting))
208 return; 205 return;
209 206
210 bool pausing = (state_ == kPausedWhenStarting); 207 bool pausing = (state_ == kPausedWhenStarting);
211 // If we are ready to start the stream, start it. 208 // If we are ready to start the stream, start it.
212 // Of course we may have to stop it immediately... 209 // Of course we may have to stop it immediately...
213 if (--number_polling_attempts_left_ == 0 || 210 if (--number_polling_attempts_left_ == 0 ||
214 pausing || 211 pausing ||
215 sync_reader_->DataReady()) { 212 sync_reader_->DataReady()) {
216 StartStream(); 213 StartStream();
217 if (pausing) { 214 if (pausing) {
218 DoPause(); 215 DoPause();
219 } 216 }
220 } else { 217 } else {
221 message_loop_->PostDelayedTask( 218 message_loop_->PostDelayedTask(
222 FROM_HERE, 219 FROM_HERE,
223 base::Bind(&AudioOutputController::PollAndStartIfDataReady, this), 220 base::Bind(&AudioOutputController::PollAndStartIfDataReady,
221 weak_this_.GetWeakPtr()),
224 kPollPauseInMilliseconds); 222 kPollPauseInMilliseconds);
225 } 223 }
226 } 224 }
227 225
228 void AudioOutputController::StartStream() { 226 void AudioOutputController::StartStream() {
229 DCHECK_EQ(message_loop_, MessageLoop::current()); 227 DCHECK_EQ(message_loop_, MessageLoop::current());
230 state_ = kPlaying; 228 state_ = kPlaying;
231 229
232 // We start the AudioOutputStream lazily. 230 // We start the AudioOutputStream lazily.
233 stream_->Start(this); 231 stream_->Start(this);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 do { 370 do {
373 base::PlatformThread::Sleep(1); 371 base::PlatformThread::Sleep(1);
374 } while (!sync_reader_->DataReady() && 372 } while (!sync_reader_->DataReady() &&
375 (Time::Now() - start_time).InMilliseconds() < kMaxPollingDelayMs); 373 (Time::Now() - start_time).InMilliseconds() < kMaxPollingDelayMs);
376 } 374 }
377 } 375 }
378 376
379 void AudioOutputController::OnError(AudioOutputStream* stream, int code) { 377 void AudioOutputController::OnError(AudioOutputStream* stream, int code) {
380 // Handle error on the audio controller thread. 378 // Handle error on the audio controller thread.
381 message_loop_->PostTask(FROM_HERE, base::Bind( 379 message_loop_->PostTask(FROM_HERE, base::Bind(
382 &AudioOutputController::DoReportError, this, code)); 380 &AudioOutputController::DoReportError, base::Unretained(this), code));
383 } 381 }
384 382
385 void AudioOutputController::SubmitOnMoreData_Locked() { 383 void AudioOutputController::SubmitOnMoreData_Locked() {
386 lock_.AssertAcquired(); 384 lock_.AssertAcquired();
387 385
388 if (buffer_.forward_bytes() > buffer_.forward_capacity()) 386 if (buffer_.forward_bytes() > buffer_.forward_capacity())
389 return; 387 return;
390 388
391 if (pending_request_) 389 if (pending_request_)
392 return; 390 return;
393 pending_request_ = true; 391 pending_request_ = true;
394 392
395 AudioBuffersState buffers_state = buffers_state_; 393 AudioBuffersState buffers_state = buffers_state_;
396 buffers_state.pending_bytes += buffer_.forward_bytes(); 394 buffers_state.pending_bytes += buffer_.forward_bytes();
397 395
398 // If we need more data then call the event handler to ask for more data. 396 // If we need more data then call the event handler to ask for more data.
399 // It is okay that we don't lock in this block because the parameters are 397 // It is okay that we don't lock in this block because the parameters are
400 // correct and in the worst case we are just asking more data than needed. 398 // correct and in the worst case we are just asking more data than needed.
401 base::AutoUnlock auto_unlock(lock_); 399 base::AutoUnlock auto_unlock(lock_);
402 handler_->OnMoreData(this, buffers_state); 400 handler_->OnMoreData(this, buffers_state);
403 } 401 }
404 402
405 void AudioOutputController::StopCloseAndClearStream() { 403 void AudioOutputController::StopCloseAndClearStream() {
406 // Allow calling unconditionally and bail if we don't have a stream_ to close. 404 // Allow calling unconditionally and bail if we don't have a stream_ to close.
407 if (!stream_) 405 if (!stream_)
408 return; 406 return;
409 stream_->Stop(); 407 stream_->Stop();
410 stream_->Close(); 408 stream_->Close();
411 stream_ = NULL; 409 stream_ = NULL;
410 weak_this_.InvalidateWeakPtrs();
412 } 411 }
413 412
414 } // namespace media 413 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_output_controller.h ('k') | media/audio/audio_output_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698