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

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

Issue 1323403005: Allow AudioOutputDevice objects to be initialized with a specific hardware output device and store … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: dalecurtis' comments Created 5 years, 3 months 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
« no previous file with comments | « media/audio/audio_output_device.h ('k') | media/audio/audio_output_device_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) 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_device.h" 5 #include "media/audio/audio_output_device.h"
6 6
7 #include <string>
8
9 #include "base/callback_helpers.h" 7 #include "base/callback_helpers.h"
10 #include "base/threading/thread_restrictions.h" 8 #include "base/threading/thread_restrictions.h"
11 #include "base/time/time.h" 9 #include "base/time/time.h"
12 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
13 #include "media/audio/audio_output_controller.h" 11 #include "media/audio/audio_output_controller.h"
14 #include "media/base/limits.h" 12 #include "media/base/limits.h"
15 13
16 namespace media { 14 namespace media {
17 15
18 // Takes care of invoking the render callback on the audio thread. 16 // Takes care of invoking the render callback on the audio thread.
(...skipping 15 matching lines...) Expand all
34 32
35 private: 33 private:
36 AudioRendererSink::RenderCallback* render_callback_; 34 AudioRendererSink::RenderCallback* render_callback_;
37 scoped_ptr<AudioBus> output_bus_; 35 scoped_ptr<AudioBus> output_bus_;
38 uint64 callback_num_; 36 uint64 callback_num_;
39 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback); 37 DISALLOW_COPY_AND_ASSIGN(AudioThreadCallback);
40 }; 38 };
41 39
42 AudioOutputDevice::AudioOutputDevice( 40 AudioOutputDevice::AudioOutputDevice(
43 scoped_ptr<AudioOutputIPC> ipc, 41 scoped_ptr<AudioOutputIPC> ipc,
44 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 42 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
43 int session_id,
44 const std::string& device_id,
45 const GURL& security_origin)
45 : ScopedTaskRunnerObserver(io_task_runner), 46 : ScopedTaskRunnerObserver(io_task_runner),
46 callback_(NULL), 47 callback_(NULL),
47 ipc_(ipc.Pass()), 48 ipc_(ipc.Pass()),
48 state_(IDLE), 49 state_(IDLE),
50 start_on_authorized_(false),
49 play_on_start_(true), 51 play_on_start_(true),
50 session_id_(-1), 52 session_id_(session_id),
53 device_id_(device_id),
54 security_origin_(security_origin),
51 stopping_hack_(false), 55 stopping_hack_(false),
52 current_switch_request_id_(0) { 56 switch_output_device_on_start_(false),
57 did_set_output_params_(true, false) {
53 CHECK(ipc_); 58 CHECK(ipc_);
54 59
55 // The correctness of the code depends on the relative values assigned in the 60 // The correctness of the code depends on the relative values assigned in the
56 // State enum. 61 // State enum.
57 static_assert(IPC_CLOSED < IDLE, "invalid enum value assignment 0"); 62 static_assert(IPC_CLOSED < IDLE, "invalid enum value assignment 0");
58 static_assert(IDLE < CREATING_STREAM, "invalid enum value assignment 1"); 63 static_assert(IDLE < AUTHORIZING, "invalid enum value assignment 1");
59 static_assert(CREATING_STREAM < PAUSED, "invalid enum value assignment 2"); 64 static_assert(AUTHORIZING < AUTHORIZED, "invalid enum value assignment 2");
60 static_assert(PAUSED < PLAYING, "invalid enum value assignment 3"); 65 static_assert(AUTHORIZED < CREATING_STREAM,
61 } 66 "invalid enum value assignment 3");
62 67 static_assert(CREATING_STREAM < PAUSED, "invalid enum value assignment 4");
63 void AudioOutputDevice::InitializeWithSessionId(const AudioParameters& params, 68 static_assert(PAUSED < PLAYING, "invalid enum value assignment 5");
64 RenderCallback* callback,
65 int session_id) {
66 DCHECK(!callback_) << "Calling InitializeWithSessionId() twice?";
67 DCHECK(params.IsValid());
68 audio_parameters_ = params;
69 callback_ = callback;
70 session_id_ = session_id;
71 } 69 }
72 70
73 void AudioOutputDevice::Initialize(const AudioParameters& params, 71 void AudioOutputDevice::Initialize(const AudioParameters& params,
74 RenderCallback* callback) { 72 RenderCallback* callback) {
75 InitializeWithSessionId(params, callback, 0); 73 DCHECK(!callback_) << "Calling Initialize() twice?";
74 DCHECK(params.IsValid());
75 audio_parameters_ = params;
76 callback_ = callback;
76 } 77 }
77 78
78 AudioOutputDevice::~AudioOutputDevice() { 79 AudioOutputDevice::~AudioOutputDevice() {
79 // The current design requires that the user calls Stop() before deleting 80 // The current design requires that the user calls Stop() before deleting
80 // this class. 81 // this class.
81 DCHECK(audio_thread_.IsStopped()); 82 DCHECK(audio_thread_.IsStopped());
82 83
83 // The following makes it possible for |current_switch_callback_| to release 84 // The following makes it possible for |current_switch_callback_| to release
84 // its bound parameters in the correct thread instead of implicitly releasing 85 // its bound parameters in the correct thread instead of implicitly releasing
85 // them in the thread where this destructor runs. 86 // them in the thread where this destructor runs.
86 if (!current_switch_callback_.is_null()) { 87 if (!current_switch_callback_.is_null()) {
87 base::ResetAndReturn(&current_switch_callback_).Run( 88 base::ResetAndReturn(&current_switch_callback_)
88 SWITCH_OUTPUT_DEVICE_RESULT_ERROR_OBSOLETE); 89 .Run(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
89 } 90 }
91
92 // If necessary, signal the reception of parameters to unblock any blocked
93 // threads
94 if (!did_set_output_params_.IsSignaled())
DaleCurtis 2015/09/14 20:07:41 You can instead DCHECK this since AOD is ref-count
Guido Urdaneta 2015/09/15 08:28:29 Done. However, I added a Signal() in OnIPCClosed()
Guido Urdaneta 2015/09/15 09:45:14 Reverted the DCHECK in the destructor. The DCHECK
95 did_set_output_params_.Signal();
96 }
97
98 void AudioOutputDevice::RequestDeviceAuthorization() {
99 task_runner()->PostTask(
100 FROM_HERE,
101 base::Bind(&AudioOutputDevice::RequestDeviceAuthorizationOnIOThread,
102 this));
90 } 103 }
91 104
92 void AudioOutputDevice::Start() { 105 void AudioOutputDevice::Start() {
93 DCHECK(callback_) << "Initialize hasn't been called"; 106 DCHECK(callback_) << "Initialize hasn't been called";
94 task_runner()->PostTask(FROM_HERE, 107 task_runner()->PostTask(FROM_HERE,
95 base::Bind(&AudioOutputDevice::CreateStreamOnIOThread, this, 108 base::Bind(&AudioOutputDevice::CreateStreamOnIOThread, this,
96 audio_parameters_)); 109 audio_parameters_));
97 } 110 }
98 111
99 void AudioOutputDevice::Stop() { 112 void AudioOutputDevice::Stop() {
(...skipping 30 matching lines...) Expand all
130 } 143 }
131 144
132 OutputDevice* AudioOutputDevice::GetOutputDevice() { 145 OutputDevice* AudioOutputDevice::GetOutputDevice() {
133 return this; 146 return this;
134 } 147 }
135 148
136 void AudioOutputDevice::SwitchOutputDevice( 149 void AudioOutputDevice::SwitchOutputDevice(
137 const std::string& device_id, 150 const std::string& device_id,
138 const GURL& security_origin, 151 const GURL& security_origin,
139 const SwitchOutputDeviceCB& callback) { 152 const SwitchOutputDeviceCB& callback) {
140 DVLOG(1) << __FUNCTION__ << "(" << device_id << ")";
141 task_runner()->PostTask( 153 task_runner()->PostTask(
142 FROM_HERE, base::Bind(&AudioOutputDevice::SwitchOutputDeviceOnIOThread, 154 FROM_HERE, base::Bind(&AudioOutputDevice::SwitchOutputDeviceOnIOThread,
143 this, device_id, security_origin, callback)); 155 this, device_id, security_origin, callback));
144 } 156 }
145 157
158 AudioParameters AudioOutputDevice::GetOutputParameters() {
159 CHECK(!task_runner()->BelongsToCurrentThread());
160 did_set_output_params_.Wait();
161 return output_params_;
162 }
163
164 void AudioOutputDevice::RequestDeviceAuthorizationOnIOThread() {
165 DCHECK(task_runner()->BelongsToCurrentThread());
166 DCHECK_EQ(state_, IDLE);
167 state_ = AUTHORIZING;
168 ipc_->RequestDeviceAuthorization(this, session_id_, device_id_,
169 security_origin_);
170 }
171
146 void AudioOutputDevice::CreateStreamOnIOThread(const AudioParameters& params) { 172 void AudioOutputDevice::CreateStreamOnIOThread(const AudioParameters& params) {
147 DCHECK(task_runner()->BelongsToCurrentThread()); 173 DCHECK(task_runner()->BelongsToCurrentThread());
148 if (state_ == IDLE) { 174 switch (state_) {
149 state_ = CREATING_STREAM; 175 case IPC_CLOSED:
150 ipc_->CreateStream(this, params, session_id_); 176 if (callback_)
177 callback_->OnRenderError();
178 break;
179
180 case IDLE:
181 if (did_set_output_params_.IsSignaled() && device_id_.empty() &&
182 security_origin_.is_empty()) {
183 state_ = CREATING_STREAM;
184 ipc_->CreateStream(this, params);
185 } else {
186 RequestDeviceAuthorizationOnIOThread();
187 start_on_authorized_ = true;
188 }
189 break;
190
191 case AUTHORIZING:
192 start_on_authorized_ = true;
193 break;
194
195 case AUTHORIZED:
196 state_ = CREATING_STREAM;
197 ipc_->CreateStream(this, params);
198 start_on_authorized_ = false;
199 break;
200
201 case CREATING_STREAM:
202 case PAUSED:
203 case PLAYING:
204 NOTREACHED();
205 break;
151 } 206 }
152 } 207 }
153 208
154 void AudioOutputDevice::PlayOnIOThread() { 209 void AudioOutputDevice::PlayOnIOThread() {
155 DCHECK(task_runner()->BelongsToCurrentThread()); 210 DCHECK(task_runner()->BelongsToCurrentThread());
156 if (state_ == PAUSED) { 211 if (state_ == PAUSED) {
157 TRACE_EVENT_ASYNC_BEGIN0( 212 TRACE_EVENT_ASYNC_BEGIN0(
158 "audio", "StartingPlayback", audio_callback_.get()); 213 "audio", "StartingPlayback", audio_callback_.get());
159 ipc_->PlayStream(); 214 ipc_->PlayStream();
160 state_ = PLAYING; 215 state_ = PLAYING;
(...skipping 11 matching lines...) Expand all
172 ipc_->PauseStream(); 227 ipc_->PauseStream();
173 state_ = PAUSED; 228 state_ = PAUSED;
174 } 229 }
175 play_on_start_ = false; 230 play_on_start_ = false;
176 } 231 }
177 232
178 void AudioOutputDevice::ShutDownOnIOThread() { 233 void AudioOutputDevice::ShutDownOnIOThread() {
179 DCHECK(task_runner()->BelongsToCurrentThread()); 234 DCHECK(task_runner()->BelongsToCurrentThread());
180 235
181 // Close the stream, if we haven't already. 236 // Close the stream, if we haven't already.
182 if (state_ >= CREATING_STREAM) { 237 if (state_ >= AUTHORIZING) {
183 ipc_->CloseStream(); 238 ipc_->CloseStream();
184 state_ = IDLE; 239 state_ = IDLE;
185 } 240 }
241 start_on_authorized_ = false;
186 242
187 // We can run into an issue where ShutDownOnIOThread is called right after 243 // We can run into an issue where ShutDownOnIOThread is called right after
188 // OnStreamCreated is called in cases where Start/Stop are called before we 244 // OnStreamCreated is called in cases where Start/Stop are called before we
189 // get the OnStreamCreated callback. To handle that corner case, we call 245 // get the OnStreamCreated callback. To handle that corner case, we call
190 // Stop(). In most cases, the thread will already be stopped. 246 // Stop(). In most cases, the thread will already be stopped.
191 // 247 //
192 // Another situation is when the IO thread goes away before Stop() is called 248 // Another situation is when the IO thread goes away before Stop() is called
193 // in which case, we cannot use the message loop to close the thread handle 249 // in which case, we cannot use the message loop to close the thread handle
194 // and can't rely on the main thread existing either. 250 // and can't rely on the main thread existing either.
195 base::AutoLock auto_lock_(audio_thread_lock_); 251 base::AutoLock auto_lock_(audio_thread_lock_);
196 base::ThreadRestrictions::ScopedAllowIO allow_io; 252 base::ThreadRestrictions::ScopedAllowIO allow_io;
197 audio_thread_.Stop(NULL); 253 audio_thread_.Stop(NULL);
198 audio_callback_.reset(); 254 audio_callback_.reset();
199 stopping_hack_ = false; 255 stopping_hack_ = false;
200 } 256 }
201 257
202 void AudioOutputDevice::SetVolumeOnIOThread(double volume) { 258 void AudioOutputDevice::SetVolumeOnIOThread(double volume) {
203 DCHECK(task_runner()->BelongsToCurrentThread()); 259 DCHECK(task_runner()->BelongsToCurrentThread());
204 if (state_ >= CREATING_STREAM) 260 if (state_ >= CREATING_STREAM)
205 ipc_->SetVolume(volume); 261 ipc_->SetVolume(volume);
206 } 262 }
207 263
208 void AudioOutputDevice::SwitchOutputDeviceOnIOThread( 264 void AudioOutputDevice::SwitchOutputDeviceOnIOThread(
209 const std::string& device_id, 265 const std::string& device_id,
210 const GURL& security_origin, 266 const GURL& security_origin,
211 const SwitchOutputDeviceCB& callback) { 267 const SwitchOutputDeviceCB& callback) {
212 DCHECK(task_runner()->BelongsToCurrentThread()); 268 DCHECK(task_runner()->BelongsToCurrentThread());
213 DVLOG(1) << __FUNCTION__ << "(" << device_id << "," << security_origin << ")"; 269
270 // Do not allow concurrent SwitchOutputDevice requests
271 if (!current_switch_callback_.is_null()) {
272 callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_INTERNAL);
273 return;
274 }
275
276 current_switch_callback_ = callback;
277 current_switch_device_id_ = device_id;
278 current_switch_security_origin_ = security_origin;
214 if (state_ >= CREATING_STREAM) { 279 if (state_ >= CREATING_STREAM) {
215 SetCurrentSwitchRequest(callback); 280 ipc_->SwitchOutputDevice(current_switch_device_id_,
216 ipc_->SwitchOutputDevice(device_id, security_origin, 281 current_switch_security_origin_);
217 current_switch_request_id_);
218 } else { 282 } else {
219 callback.Run(SWITCH_OUTPUT_DEVICE_RESULT_ERROR_NOT_SUPPORTED); 283 switch_output_device_on_start_ = true;
220 } 284 }
221 } 285 }
222 286
223 void AudioOutputDevice::OnStateChanged(AudioOutputIPCDelegateState state) { 287 void AudioOutputDevice::OnStateChanged(AudioOutputIPCDelegateState state) {
224 DCHECK(task_runner()->BelongsToCurrentThread()); 288 DCHECK(task_runner()->BelongsToCurrentThread());
225 289
226 // Do nothing if the stream has been closed. 290 // Do nothing if the stream has been closed.
227 if (state_ < CREATING_STREAM) 291 if (state_ < CREATING_STREAM)
228 return; 292 return;
229 293
(...skipping 13 matching lines...) Expand all
243 // a callback object via Start() and clear it in Stop(). 307 // a callback object via Start() and clear it in Stop().
244 if (!audio_thread_.IsStopped()) 308 if (!audio_thread_.IsStopped())
245 callback_->OnRenderError(); 309 callback_->OnRenderError();
246 break; 310 break;
247 default: 311 default:
248 NOTREACHED(); 312 NOTREACHED();
249 break; 313 break;
250 } 314 }
251 } 315 }
252 316
317 void AudioOutputDevice::OnDeviceAuthorized(
318 bool success,
319 const media::AudioParameters& output_params) {
320 DCHECK(task_runner()->BelongsToCurrentThread());
321 DCHECK(state_ == AUTHORIZING);
322
323 if (success) {
324 state_ = AUTHORIZED;
325 if (!did_set_output_params_.IsSignaled())
DaleCurtis 2015/09/14 20:07:41 Is it possible to get two of these? Should this be
Guido Urdaneta 2015/09/15 08:28:29 It is possible to get two of these in a Start()/St
326 output_params_ = output_params;
327 if (start_on_authorized_)
328 CreateStreamOnIOThread(audio_parameters_);
329 } else {
330 OnIPCClosed();
331 if (callback_)
332 callback_->OnRenderError();
333 }
334
335 did_set_output_params_.Signal();
336 }
337
253 void AudioOutputDevice::OnStreamCreated( 338 void AudioOutputDevice::OnStreamCreated(
254 base::SharedMemoryHandle handle, 339 base::SharedMemoryHandle handle,
255 base::SyncSocket::Handle socket_handle, 340 base::SyncSocket::Handle socket_handle,
256 int length) { 341 int length) {
257 DCHECK(task_runner()->BelongsToCurrentThread()); 342 DCHECK(task_runner()->BelongsToCurrentThread());
258 DCHECK(base::SharedMemory::IsHandleValid(handle)); 343 DCHECK(base::SharedMemory::IsHandleValid(handle));
259 #if defined(OS_WIN) 344 #if defined(OS_WIN)
260 DCHECK(socket_handle); 345 DCHECK(socket_handle);
261 #else 346 #else
262 DCHECK_GE(socket_handle, 0); 347 DCHECK_GE(socket_handle, 0);
263 #endif 348 #endif
264 DCHECK_GT(length, 0); 349 DCHECK_GT(length, 0);
265 350
266 if (state_ != CREATING_STREAM) 351 if (state_ != CREATING_STREAM)
267 return; 352 return;
268 353
269 // We can receive OnStreamCreated() on the IO thread after the client has 354 // We can receive OnStreamCreated() on the IO thread after the client has
270 // called Stop() but before ShutDownOnIOThread() is processed. In such a 355 // called Stop() but before ShutDownOnIOThread() is processed. In such a
271 // situation |callback_| might point to freed memory. Instead of starting 356 // situation |callback_| might point to freed memory. Instead of starting
272 // |audio_thread_| do nothing and wait for ShutDownOnIOThread() to get called. 357 // |audio_thread_| do nothing and wait for ShutDownOnIOThread() to get called.
273 // 358 //
274 // TODO(scherkus): The real fix is to have sane ownership semantics. The fact 359 // TODO(scherkus): The real fix is to have sane ownership semantics. The fact
275 // that |callback_| (which should own and outlive this object!) can point to 360 // that |callback_| (which should own and outlive this object!) can point to
276 // freed memory is a mess. AudioRendererSink should be non-refcounted so that 361 // freed memory is a mess. AudioRendererSink should be non-refcounted so that
277 // owners (WebRtcAudioDeviceImpl, AudioRendererImpl, etc...) can Stop() and 362 // owners (WebRtcAudioDeviceImpl, AudioRendererImpl, etc...) can Stop() and
278 // delete as they see fit. AudioOutputDevice should internally use WeakPtr 363 // delete as they see fit. AudioOutputDevice should internally use WeakPtr
279 // to handle teardown and thread hopping. See http://crbug.com/151051 for 364 // to handle teardown and thread hopping. See http://crbug.com/151051 for
280 // details. 365 // details.
281 base::AutoLock auto_lock(audio_thread_lock_); 366 {
282 if (stopping_hack_) 367 base::AutoLock auto_lock(audio_thread_lock_);
283 return; 368 if (stopping_hack_)
369 return;
284 370
285 DCHECK(audio_thread_.IsStopped()); 371 DCHECK(audio_thread_.IsStopped());
286 audio_callback_.reset(new AudioOutputDevice::AudioThreadCallback( 372 audio_callback_.reset(new AudioOutputDevice::AudioThreadCallback(
287 audio_parameters_, handle, length, callback_)); 373 audio_parameters_, handle, length, callback_));
288 audio_thread_.Start( 374 audio_thread_.Start(audio_callback_.get(), socket_handle,
289 audio_callback_.get(), socket_handle, "AudioOutputDevice", true); 375 "AudioOutputDevice", true);
290 state_ = PAUSED; 376 state_ = PAUSED;
291 377
292 // We handle the case where Play() and/or Pause() may have been called 378 // We handle the case where Play() and/or Pause() may have been called
293 // multiple times before OnStreamCreated() gets called. 379 // multiple times before OnStreamCreated() gets called.
294 if (play_on_start_) 380 if (play_on_start_)
295 PlayOnIOThread(); 381 PlayOnIOThread();
296 } 382 }
297 383
298 void AudioOutputDevice::SetCurrentSwitchRequest( 384 if (switch_output_device_on_start_) {
299 const SwitchOutputDeviceCB& callback) { 385 ipc_->SwitchOutputDevice(current_switch_device_id_,
300 DCHECK(task_runner()->BelongsToCurrentThread()); 386 current_switch_security_origin_);
301 DVLOG(1) << __FUNCTION__;
302 // If there is a previous unresolved request, resolve it as obsolete
303 if (!current_switch_callback_.is_null()) {
304 base::ResetAndReturn(&current_switch_callback_).Run(
305 SWITCH_OUTPUT_DEVICE_RESULT_ERROR_OBSOLETE);
306 } 387 }
307 current_switch_callback_ = callback;
308 current_switch_request_id_++;
309 } 388 }
310 389
311 void AudioOutputDevice::OnOutputDeviceSwitched( 390 void AudioOutputDevice::OnOutputDeviceSwitched(
312 int request_id,
313 SwitchOutputDeviceResult result) { 391 SwitchOutputDeviceResult result) {
314 DCHECK(task_runner()->BelongsToCurrentThread()); 392 DCHECK(task_runner()->BelongsToCurrentThread());
315 DCHECK(request_id <= current_switch_request_id_); 393 if (result == SWITCH_OUTPUT_DEVICE_RESULT_SUCCESS) {
316 DVLOG(1) << __FUNCTION__ 394 session_id_ = 0; // Output device is no longer attached to an input device
317 << "(" << request_id << ", " << result << ")"; 395 device_id_ = current_switch_device_id_;
318 if (request_id != current_switch_request_id_) { 396 security_origin_ = current_switch_security_origin_;
319 return;
320 } 397 }
398 DCHECK(!current_switch_callback_.is_null());
321 base::ResetAndReturn(&current_switch_callback_).Run(result); 399 base::ResetAndReturn(&current_switch_callback_).Run(result);
322 } 400 }
323 401
324 void AudioOutputDevice::OnIPCClosed() { 402 void AudioOutputDevice::OnIPCClosed() {
325 DCHECK(task_runner()->BelongsToCurrentThread()); 403 DCHECK(task_runner()->BelongsToCurrentThread());
326 state_ = IPC_CLOSED; 404 state_ = IPC_CLOSED;
327 ipc_.reset(); 405 ipc_.reset();
328 } 406 }
329 407
330 void AudioOutputDevice::WillDestroyCurrentMessageLoop() { 408 void AudioOutputDevice::WillDestroyCurrentMessageLoop() {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 TRACE_EVENT_ASYNC_END0("audio", "StartingPlayback", this); 449 TRACE_EVENT_ASYNC_END0("audio", "StartingPlayback", this);
372 } 450 }
373 451
374 // Update the audio-delay measurement then ask client to render audio. Since 452 // Update the audio-delay measurement then ask client to render audio. Since
375 // |output_bus_| is wrapping the shared memory the Render() call is writing 453 // |output_bus_| is wrapping the shared memory the Render() call is writing
376 // directly into the shared memory. 454 // directly into the shared memory.
377 render_callback_->Render(output_bus_.get(), audio_delay_milliseconds); 455 render_callback_->Render(output_bus_.get(), audio_delay_milliseconds);
378 } 456 }
379 457
380 } // namespace media. 458 } // namespace media.
OLDNEW
« no previous file with comments | « media/audio/audio_output_device.h ('k') | media/audio/audio_output_device_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698