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

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

Powered by Google App Engine
This is Rietveld 408576698