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

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

Issue 188243002: Fix AudioEntry destruction order. Add debugging CHECKs for racy shutdown. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Typos. Created 6 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « media/audio/audio_output_controller.h ('k') | no next file » | 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_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/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/task_runner_util.h" 10 #include "base/task_runner_util.h"
(...skipping 27 matching lines...) Expand all
38 const std::string& output_device_id, 38 const std::string& output_device_id,
39 SyncReader* sync_reader) 39 SyncReader* sync_reader)
40 : audio_manager_(audio_manager), 40 : audio_manager_(audio_manager),
41 params_(params), 41 params_(params),
42 handler_(handler), 42 handler_(handler),
43 output_device_id_(output_device_id), 43 output_device_id_(output_device_id),
44 stream_(NULL), 44 stream_(NULL),
45 diverting_to_stream_(NULL), 45 diverting_to_stream_(NULL),
46 volume_(1.0), 46 volume_(1.0),
47 state_(kEmpty), 47 state_(kEmpty),
48 num_allowed_io_(0), 48 currently_in_on_more_io_data_(0),
49 sync_reader_(sync_reader), 49 sync_reader_(sync_reader),
50 message_loop_(audio_manager->GetTaskRunner()), 50 message_loop_(audio_manager->GetTaskRunner()),
51 #if defined(AUDIO_POWER_MONITORING) 51 #if defined(AUDIO_POWER_MONITORING)
52 power_monitor_( 52 power_monitor_(
53 params.sample_rate(), 53 params.sample_rate(),
54 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)), 54 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMillis)),
55 #endif 55 #endif
56 on_more_io_data_called_(0) { 56 on_more_io_data_called_(0) {
57 DCHECK(audio_manager); 57 DCHECK(audio_manager);
58 DCHECK(handler_); 58 DCHECK(handler_);
59 DCHECK(sync_reader_); 59 DCHECK(sync_reader_);
60 DCHECK(message_loop_.get()); 60 DCHECK(message_loop_.get());
61 } 61 }
62 62
63 AudioOutputController::~AudioOutputController() { 63 AudioOutputController::~AudioOutputController() {
64 DCHECK_EQ(kClosed, state_); 64 DCHECK_EQ(kClosed, state_);
65 // TODO(dalecurtis): Remove debugging for http://crbug.com/349651
66 CHECK(base::AtomicRefCountIsZero(&currently_in_on_more_io_data_));
acolwell GONE FROM CHROMIUM 2014/03/06 20:54:10 I'm a little unclear why we need this. Who owns th
DaleCurtis 2014/03/06 21:21:11 See audio_io.h and the AudioSourceCallback interfa
65 } 67 }
66 68
67 // static 69 // static
68 scoped_refptr<AudioOutputController> AudioOutputController::Create( 70 scoped_refptr<AudioOutputController> AudioOutputController::Create(
69 AudioManager* audio_manager, 71 AudioManager* audio_manager,
70 EventHandler* event_handler, 72 EventHandler* event_handler,
71 const AudioParameters& params, 73 const AudioParameters& params,
72 const std::string& output_device_id, 74 const std::string& output_device_id,
73 SyncReader* sync_reader) { 75 SyncReader* sync_reader) {
74 DCHECK(audio_manager); 76 DCHECK(audio_manager);
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 #if defined(AUDIO_POWER_MONITORING) 186 #if defined(AUDIO_POWER_MONITORING)
185 power_monitor_.Reset(); 187 power_monitor_.Reset();
186 power_poll_callback_.Reset( 188 power_poll_callback_.Reset(
187 base::Bind(&AudioOutputController::ReportPowerMeasurementPeriodically, 189 base::Bind(&AudioOutputController::ReportPowerMeasurementPeriodically,
188 this)); 190 this));
189 // Run the callback to send an initial notification that we're starting in 191 // Run the callback to send an initial notification that we're starting in
190 // silence, and to schedule periodic callbacks. 192 // silence, and to schedule periodic callbacks.
191 power_poll_callback_.callback().Run(); 193 power_poll_callback_.callback().Run();
192 #endif 194 #endif
193 195
194 on_more_io_data_called_ = 0;
195 AllowEntryToOnMoreIOData();
196 stream_->Start(this); 196 stream_->Start(this);
197 197
198 // For UMA tracking purposes, start the wedge detection timer. This allows us 198 // For UMA tracking purposes, start the wedge detection timer. This allows us
199 // to record statistics about the number of wedged playbacks in the field. 199 // to record statistics about the number of wedged playbacks in the field.
200 // 200 //
201 // WedgeCheck() will look to see if |on_more_io_data_called_| is true after 201 // WedgeCheck() will look to see if |on_more_io_data_called_| is true after
202 // the timeout expires. Care must be taken to ensure the wedge check delay is 202 // the timeout expires. Care must be taken to ensure the wedge check delay is
203 // large enough that the value isn't queried while OnMoreDataIO() is setting 203 // large enough that the value isn't queried while OnMoreDataIO() is setting
204 // it. 204 // it.
205 // 205 //
(...skipping 19 matching lines...) Expand all
225 TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond); 225 TimeDelta::FromSeconds(1) / kPowerMeasurementsPerSecond);
226 } 226 }
227 #endif 227 #endif
228 228
229 void AudioOutputController::StopStream() { 229 void AudioOutputController::StopStream() {
230 DCHECK(message_loop_->BelongsToCurrentThread()); 230 DCHECK(message_loop_->BelongsToCurrentThread());
231 231
232 if (state_ == kPlaying) { 232 if (state_ == kPlaying) {
233 wedge_timer_.reset(); 233 wedge_timer_.reset();
234 stream_->Stop(); 234 stream_->Stop();
235 DisallowEntryToOnMoreIOData();
236 235
237 #if defined(AUDIO_POWER_MONITORING) 236 #if defined(AUDIO_POWER_MONITORING)
238 power_poll_callback_.Cancel(); 237 power_poll_callback_.Cancel();
239 #endif 238 #endif
240 239
241 state_ = kPaused; 240 state_ = kPaused;
242 } 241 }
243 } 242 }
244 243
245 void AudioOutputController::DoPause() { 244 void AudioOutputController::DoPause() {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 } 326 }
328 327
329 int AudioOutputController::OnMoreData(AudioBus* dest, 328 int AudioOutputController::OnMoreData(AudioBus* dest,
330 AudioBuffersState buffers_state) { 329 AudioBuffersState buffers_state) {
331 return OnMoreIOData(NULL, dest, buffers_state); 330 return OnMoreIOData(NULL, dest, buffers_state);
332 } 331 }
333 332
334 int AudioOutputController::OnMoreIOData(AudioBus* source, 333 int AudioOutputController::OnMoreIOData(AudioBus* source,
335 AudioBus* dest, 334 AudioBus* dest,
336 AudioBuffersState buffers_state) { 335 AudioBuffersState buffers_state) {
337 DisallowEntryToOnMoreIOData(); 336 base::AtomicRefCountInc(&currently_in_on_more_io_data_);
acolwell GONE FROM CHROMIUM 2014/03/06 20:54:10 If you make the initial value 1 and dec instead of
DaleCurtis 2014/03/06 21:21:11 Done.
338 TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData"); 337 TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData");
339 338
340 // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck() 339 // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck()
341 // may have already fired if OnMoreIOData() took an abnormal amount of time). 340 // may have already fired if OnMoreIOData() took an abnormal amount of time).
342 // Since this thread is the only writer of |on_more_io_data_called_| once the 341 // Since this thread is the only writer of |on_more_io_data_called_| once the
343 // thread starts, its safe to compare and then increment. 342 // thread starts, its safe to compare and then increment.
344 if (base::AtomicRefCountIsZero(&on_more_io_data_called_)) 343 if (base::AtomicRefCountIsZero(&on_more_io_data_called_))
345 base::AtomicRefCountInc(&on_more_io_data_called_); 344 base::AtomicRefCountInc(&on_more_io_data_called_);
346 345
347 sync_reader_->Read(source, dest); 346 sync_reader_->Read(source, dest);
348 347
349 const int frames = dest->frames(); 348 const int frames = dest->frames();
350 sync_reader_->UpdatePendingBytes( 349 sync_reader_->UpdatePendingBytes(
351 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame()); 350 buffers_state.total_bytes() + frames * params_.GetBytesPerFrame());
352 351
353 #if defined(AUDIO_POWER_MONITORING) 352 #if defined(AUDIO_POWER_MONITORING)
354 power_monitor_.Scan(*dest, frames); 353 power_monitor_.Scan(*dest, frames);
355 #endif 354 #endif
356 355
357 AllowEntryToOnMoreIOData(); 356 CHECK(!base::AtomicRefCountDec(&currently_in_on_more_io_data_));
358 return frames; 357 return frames;
359 } 358 }
360 359
361 void AudioOutputController::OnError(AudioOutputStream* stream) { 360 void AudioOutputController::OnError(AudioOutputStream* stream) {
362 // Handle error on the audio controller thread. 361 // Handle error on the audio controller thread.
363 message_loop_->PostTask(FROM_HERE, base::Bind( 362 message_loop_->PostTask(FROM_HERE, base::Bind(
364 &AudioOutputController::DoReportError, this)); 363 &AudioOutputController::DoReportError, this));
365 } 364 }
366 365
367 void AudioOutputController::DoStopCloseAndClearStream() { 366 void AudioOutputController::DoStopCloseAndClearStream() {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 if (state_ == kClosed) 448 if (state_ == kClosed)
450 return; 449 return;
451 450
452 // Note: OnDeviceChange() will cause the existing stream (the consumer of the 451 // Note: OnDeviceChange() will cause the existing stream (the consumer of the
453 // diverted audio data) to be closed, and diverting_to_stream_ will be set 452 // diverted audio data) to be closed, and diverting_to_stream_ will be set
454 // back to NULL. 453 // back to NULL.
455 OnDeviceChange(); 454 OnDeviceChange();
456 DCHECK(!diverting_to_stream_); 455 DCHECK(!diverting_to_stream_);
457 } 456 }
458 457
459 void AudioOutputController::AllowEntryToOnMoreIOData() {
460 DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_));
461 base::AtomicRefCountInc(&num_allowed_io_);
462 }
463
464 void AudioOutputController::DisallowEntryToOnMoreIOData() {
465 const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_);
466 DCHECK(is_zero);
467 }
468
469 void AudioOutputController::WedgeCheck() { 458 void AudioOutputController::WedgeCheck() {
470 DCHECK(message_loop_->BelongsToCurrentThread()); 459 DCHECK(message_loop_->BelongsToCurrentThread());
471 460
472 // If we should be playing and we haven't, that's a wedge. 461 // If we should be playing and we haven't, that's a wedge.
473 if (state_ == kPlaying) { 462 if (state_ == kPlaying) {
474 const bool playback_success = 463 const bool playback_success =
475 base::AtomicRefCountIsOne(&on_more_io_data_called_); 464 base::AtomicRefCountIsOne(&on_more_io_data_called_);
476 465
477 UMA_HISTOGRAM_BOOLEAN( 466 UMA_HISTOGRAM_BOOLEAN(
478 "Media.AudioOutputControllerPlaybackStartupSuccess", playback_success); 467 "Media.AudioOutputControllerPlaybackStartupSuccess", playback_success);
479 468
480 // Let the AudioManager try and fix it. 469 // Let the AudioManager try and fix it.
481 if (!playback_success) 470 if (!playback_success)
482 audio_manager_->FixWedgedAudio(); 471 audio_manager_->FixWedgedAudio();
483 } 472 }
484 } 473 }
485 474
486 } // namespace media 475 } // namespace media
OLDNEW
« no previous file with comments | « media/audio/audio_output_controller.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698