audio_output_controller.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
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
3// found in the LICENSE file.
4
5#include "media/audio/audio_output_controller.h"
6
7#include "base/bind.h"
8#include "base/debug/trace_event.h"
9#include "base/message_loop.h"
10#include "base/metrics/histogram.h"
11#include "base/threading/platform_thread.h"
12#include "base/time.h"
13#include "build/build_config.h"
14#include "media/audio/audio_silence_detector.h"
15#include "media/audio/audio_util.h"
16#include "media/audio/shared_memory_util.h"
17
18using base::Time;
19using base::TimeDelta;
20
21namespace media {
22
23// Amount of contiguous time where all audio is silent before considering the
24// stream to have transitioned and EventHandler::OnAudible() should be called.
25static const int kQuestionableSilencePeriodMillis = 50;
26
27// Sample value range below which audio is considered indistinguishably silent.
28//
29// TODO(miu): This value should be specified in dbFS units rather than full
30// scale.  See TODO in audio_silence_detector.h.
31static const float kIndistinguishableSilenceThreshold =
32    1.0f / 4096.0f;  // Note: This is approximately -72 dbFS.
33
34// Polling-related constants.
35const int AudioOutputController::kPollNumAttempts = 3;
36const int AudioOutputController::kPollPauseInMilliseconds = 3;
37
38AudioOutputController::AudioOutputController(AudioManager* audio_manager,
39                                             EventHandler* handler,
40                                             const AudioParameters& params,
41                                             SyncReader* sync_reader)
42    : audio_manager_(audio_manager),
43      params_(params),
44      handler_(handler),
45      stream_(NULL),
46      diverting_to_stream_(NULL),
47      volume_(1.0),
48      state_(kEmpty),
49      num_allowed_io_(0),
50      sync_reader_(sync_reader),
51      message_loop_(audio_manager->GetMessageLoop()),
52      number_polling_attempts_left_(0),
53      weak_this_(this) {
54  DCHECK(audio_manager);
55  DCHECK(handler_);
56  DCHECK(sync_reader_);
57  DCHECK(message_loop_);
58}
59
60AudioOutputController::~AudioOutputController() {
61  DCHECK_EQ(kClosed, state_);
62}
63
64// static
65scoped_refptr<AudioOutputController> AudioOutputController::Create(
66    AudioManager* audio_manager,
67    EventHandler* event_handler,
68    const AudioParameters& params,
69    SyncReader* sync_reader) {
70  DCHECK(audio_manager);
71  DCHECK(sync_reader);
72
73  if (!params.IsValid() || !audio_manager)
74    return NULL;
75
76  scoped_refptr<AudioOutputController> controller(new AudioOutputController(
77      audio_manager, event_handler, params, sync_reader));
78  controller->message_loop_->PostTask(FROM_HERE, base::Bind(
79      &AudioOutputController::DoCreate, controller, false));
80  return controller;
81}
82
83void AudioOutputController::Play() {
84  message_loop_->PostTask(FROM_HERE, base::Bind(
85      &AudioOutputController::DoPlay, this));
86}
87
88void AudioOutputController::Pause() {
89  message_loop_->PostTask(FROM_HERE, base::Bind(
90      &AudioOutputController::DoPause, this));
91}
92
93void AudioOutputController::Close(const base::Closure& closed_task) {
94  DCHECK(!closed_task.is_null());
95  message_loop_->PostTaskAndReply(FROM_HERE, base::Bind(
96      &AudioOutputController::DoClose, this), closed_task);
97}
98
99void AudioOutputController::SetVolume(double volume) {
100  message_loop_->PostTask(FROM_HERE, base::Bind(
101      &AudioOutputController::DoSetVolume, this, volume));
102}
103
104void AudioOutputController::DoCreate(bool is_for_device_change) {
105  DCHECK(message_loop_->BelongsToCurrentThread());
106
107  // Close() can be called before DoCreate() is executed.
108  if (state_ == kClosed)
109    return;
110
111  DoStopCloseAndClearStream();  // Calls RemoveOutputDeviceChangeListener().
112  DCHECK_EQ(kEmpty, state_);
113
114  stream_ = diverting_to_stream_ ? diverting_to_stream_ :
115      audio_manager_->MakeAudioOutputStreamProxy(params_);
116  if (!stream_) {
117    state_ = kError;
118    handler_->OnError();
119    return;
120  }
121
122  if (!stream_->Open()) {
123    DoStopCloseAndClearStream();
124    state_ = kError;
125    handler_->OnError();
126    return;
127  }
128
129  // Everything started okay, so re-register for state change callbacks if
130  // stream_ was created via AudioManager.
131  if (stream_ != diverting_to_stream_)
132    audio_manager_->AddOutputDeviceChangeListener(this);
133
134  // We have successfully opened the stream. Set the initial volume.
135  stream_->SetVolume(volume_);
136
137  // Finally set the state to kCreated.
138  state_ = kCreated;
139
140  // And then report we have been created if we haven't done so already.
141  if (!is_for_device_change)
142    handler_->OnCreated();
143}
144
145void AudioOutputController::DoPlay() {
146  DCHECK(message_loop_->BelongsToCurrentThread());
147
148  // We can start from created or paused state.
149  if (state_ != kCreated && state_ != kPaused)
150    return;
151
152  state_ = kStarting;
153
154  // Ask for first packet.
155  sync_reader_->UpdatePendingBytes(0);
156
157  // Cannot start stream immediately, should give renderer some time
158  // to deliver data.
159  // TODO(vrk): The polling here and in WaitTillDataReady() is pretty clunky.
160  // Refine the API such that polling is no longer needed. (crbug.com/112196)
161  number_polling_attempts_left_ = kPollNumAttempts;
162  DCHECK(!weak_this_.HasWeakPtrs());
163  message_loop_->PostDelayedTask(
164      FROM_HERE,
165      base::Bind(&AudioOutputController::PollAndStartIfDataReady,
166      weak_this_.GetWeakPtr()),
167      TimeDelta::FromMilliseconds(kPollPauseInMilliseconds));
168}
169
170void AudioOutputController::PollAndStartIfDataReady() {
171  DCHECK(message_loop_->BelongsToCurrentThread());
172
173  DCHECK_EQ(kStarting, state_);
174
175  // If we are ready to start the stream, start it.
176  if (--number_polling_attempts_left_ == 0 ||
177      sync_reader_->DataReady()) {
178    StartStream();
179  } else {
180    message_loop_->PostDelayedTask(
181        FROM_HERE,
182        base::Bind(&AudioOutputController::PollAndStartIfDataReady,
183        weak_this_.GetWeakPtr()),
184        TimeDelta::FromMilliseconds(kPollPauseInMilliseconds));
185  }
186}
187
188void AudioOutputController::StartStream() {
189  DCHECK(message_loop_->BelongsToCurrentThread());
190  state_ = kPlaying;
191
192  silence_detector_.reset(new AudioSilenceDetector(
193      params_.sample_rate(),
194      TimeDelta::FromMilliseconds(kQuestionableSilencePeriodMillis),
195      kIndistinguishableSilenceThreshold));
196
197  // We start the AudioOutputStream lazily.
198  AllowEntryToOnMoreIOData();
199  stream_->Start(this);
200
201  // Tell the event handler that we are now playing, and also start the silence
202  // detection notifications.
203  handler_->OnPlaying();
204  silence_detector_->Start(
205      base::Bind(&EventHandler::OnAudible, base::Unretained(handler_)));
206}
207
208void AudioOutputController::StopStream() {
209  DCHECK(message_loop_->BelongsToCurrentThread());
210
211  if (state_ == kStarting) {
212    // Cancel in-progress polling start.
213    weak_this_.InvalidateWeakPtrs();
214    state_ = kPaused;
215  } else if (state_ == kPlaying) {
216    stream_->Stop();
217    DisallowEntryToOnMoreIOData();
218    silence_detector_->Stop(true);
219    silence_detector_.reset();
220    state_ = kPaused;
221  }
222}
223
224void AudioOutputController::DoPause() {
225  DCHECK(message_loop_->BelongsToCurrentThread());
226
227  StopStream();
228
229  if (state_ != kPaused)
230    return;
231
232  // Send a special pause mark to the low-latency audio thread.
233  sync_reader_->UpdatePendingBytes(kPauseMark);
234
235  handler_->OnPaused();
236}
237
238void AudioOutputController::DoClose() {
239  DCHECK(message_loop_->BelongsToCurrentThread());
240
241  if (state_ != kClosed) {
242    DoStopCloseAndClearStream();
243    sync_reader_->Close();
244    state_ = kClosed;
245  }
246}
247
248void AudioOutputController::DoSetVolume(double volume) {
249  DCHECK(message_loop_->BelongsToCurrentThread());
250
251  // Saves the volume to a member first. We may not be able to set the volume
252  // right away but when the stream is created we'll set the volume.
253  volume_ = volume;
254
255  switch (state_) {
256    case kCreated:
257    case kStarting:
258    case kPlaying:
259    case kPaused:
260      stream_->SetVolume(volume_);
261      break;
262    default:
263      return;
264  }
265}
266
267void AudioOutputController::DoReportError() {
268  DCHECK(message_loop_->BelongsToCurrentThread());
269  if (state_ != kClosed)
270    handler_->OnError();
271}
272
273int AudioOutputController::OnMoreData(AudioBus* dest,
274                                      AudioBuffersState buffers_state) {
275  return OnMoreIOData(NULL, dest, buffers_state);
276}
277
278int AudioOutputController::OnMoreIOData(AudioBus* source,
279                                        AudioBus* dest,
280                                        AudioBuffersState buffers_state) {
281  DisallowEntryToOnMoreIOData();
282  TRACE_EVENT0("audio", "AudioOutputController::OnMoreIOData");
283
284  // The OS level audio APIs on Linux and Windows all have problems requesting
285  // data on a fixed interval.  Sometimes they will issue calls back to back
286  // which can cause glitching, so wait until the renderer is ready for Read().
287  //
288  // See many bugs for context behind this decision: http://crbug.com/170498,
289  // http://crbug.com/171651, http://crbug.com/174985, and more.
290#if defined(OS_WIN) || defined(OS_LINUX)
291  WaitTillDataReady();
292#endif
293
294  const int frames = sync_reader_->Read(source, dest);
295  DCHECK_LE(0, frames);
296  sync_reader_->UpdatePendingBytes(
297      buffers_state.total_bytes() + frames * params_.GetBytesPerFrame());
298
299  silence_detector_->Scan(dest, frames);
300
301  AllowEntryToOnMoreIOData();
302  return frames;
303}
304
305void AudioOutputController::WaitTillDataReady() {
306  // Most of the time the data is ready already.
307  if (sync_reader_->DataReady())
308    return;
309
310  base::TimeTicks start = base::TimeTicks::Now();
311#if defined(OS_WIN)
312  // Wait for up to 683ms for DataReady().  683ms was chosen because it's larger
313  // than the playback time of the WaveOut buffer size using the minimum
314  // supported sample rate: 2048 / 3000 = ~683ms.
315  // TODO(davemoore): We think this can be reduced to 20ms based on
316  // http://crrev.com/180102 but will do that in separate cl for mergability.
317  const base::TimeDelta kMaxWait = base::TimeDelta::FromMilliseconds(683);
318  const base::TimeDelta kSleep = base::TimeDelta::FromMilliseconds(0);
319#else
320  const base::TimeDelta kMaxWait = base::TimeDelta::FromMilliseconds(20);
321  // We want to sleep for a bit here, as otherwise a backgrounded renderer won't
322  // get enough cpu to send the data and the high priority thread in the browser
323  // will use up a core causing even more skips.
324  const base::TimeDelta kSleep = base::TimeDelta::FromMilliseconds(2);
325#endif
326  base::TimeDelta time_since_start;
327  do {
328    base::PlatformThread::Sleep(kSleep);
329    time_since_start = base::TimeTicks::Now() - start;
330  } while (!sync_reader_->DataReady() && (time_since_start < kMaxWait));
331  UMA_HISTOGRAM_CUSTOM_TIMES("Media.AudioOutputControllerDataNotReady",
332                             time_since_start,
333                             base::TimeDelta::FromMilliseconds(1),
334                             base::TimeDelta::FromMilliseconds(1000),
335                             50);
336}
337
338void AudioOutputController::OnError(AudioOutputStream* stream) {
339  // Handle error on the audio controller thread.
340  message_loop_->PostTask(FROM_HERE, base::Bind(
341      &AudioOutputController::DoReportError, this));
342}
343
344void AudioOutputController::DoStopCloseAndClearStream() {
345  DCHECK(message_loop_->BelongsToCurrentThread());
346
347  // Allow calling unconditionally and bail if we don't have a stream_ to close.
348  if (stream_) {
349    // De-register from state change callbacks if stream_ was created via
350    // AudioManager.
351    if (stream_ != diverting_to_stream_)
352      audio_manager_->RemoveOutputDeviceChangeListener(this);
353
354    StopStream();
355    stream_->Close();
356    if (stream_ == diverting_to_stream_)
357      diverting_to_stream_ = NULL;
358    stream_ = NULL;
359  }
360
361  state_ = kEmpty;
362}
363
364void AudioOutputController::OnDeviceChange() {
365  DCHECK(message_loop_->BelongsToCurrentThread());
366
367  // TODO(dalecurtis): Notify the renderer side that a device change has
368  // occurred.  Currently querying the hardware information here will lead to
369  // crashes on OSX.  See http://crbug.com/158170.
370
371  // Recreate the stream (DoCreate() will first shut down an existing stream).
372  // Exit if we ran into an error.
373  const State original_state = state_;
374  DoCreate(true);
375  if (!stream_ || state_ == kError)
376    return;
377
378  // Get us back to the original state or an equivalent state.
379  switch (original_state) {
380    case kStarting:
381    case kPlaying:
382      DoPlay();
383      return;
384    case kCreated:
385    case kPaused:
386      // From the outside these two states are equivalent.
387      return;
388    default:
389      NOTREACHED() << "Invalid original state.";
390  }
391}
392
393const AudioParameters& AudioOutputController::GetAudioParameters() {
394  return params_;
395}
396
397void AudioOutputController::StartDiverting(AudioOutputStream* to_stream) {
398  message_loop_->PostTask(
399      FROM_HERE,
400      base::Bind(&AudioOutputController::DoStartDiverting, this, to_stream));
401}
402
403void AudioOutputController::StopDiverting() {
404  message_loop_->PostTask(
405      FROM_HERE, base::Bind(&AudioOutputController::DoStopDiverting, this));
406}
407
408void AudioOutputController::DoStartDiverting(AudioOutputStream* to_stream) {
409  DCHECK(message_loop_->BelongsToCurrentThread());
410
411  if (state_ == kClosed)
412    return;
413
414  DCHECK(!diverting_to_stream_);
415  diverting_to_stream_ = to_stream;
416  // Note: OnDeviceChange() will engage the "re-create" process, which will
417  // detect and use the alternate AudioOutputStream rather than create a new one
418  // via AudioManager.
419  OnDeviceChange();
420}
421
422void AudioOutputController::DoStopDiverting() {
423  DCHECK(message_loop_->BelongsToCurrentThread());
424
425  if (state_ == kClosed)
426    return;
427
428  // Note: OnDeviceChange() will cause the existing stream (the consumer of the
429  // diverted audio data) to be closed, and diverting_to_stream_ will be set
430  // back to NULL.
431  OnDeviceChange();
432  DCHECK(!diverting_to_stream_);
433}
434
435void AudioOutputController::AllowEntryToOnMoreIOData() {
436  DCHECK(base::AtomicRefCountIsZero(&num_allowed_io_));
437  base::AtomicRefCountInc(&num_allowed_io_);
438}
439
440void AudioOutputController::DisallowEntryToOnMoreIOData() {
441  const bool is_zero = !base::AtomicRefCountDec(&num_allowed_io_);
442  DCHECK(is_zero);
443}
444
445}  // namespace media
446