alsa_output.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2013 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// THREAD SAFETY
6//
7// AlsaPcmOutputStream object is *not* thread-safe and should only be used
8// from the audio thread.  We DCHECK on this assumption whenever we can.
9//
10// SEMANTICS OF Close()
11//
12// Close() is responsible for cleaning up any resources that were acquired after
13// a successful Open().  Close() will nullify any scheduled outstanding runnable
14// methods.
15//
16//
17// SEMANTICS OF ERROR STATES
18//
19// The object has two distinct error states: |state_| == kInError
20// and |stop_stream_|.  The |stop_stream_| variable is used to indicate
21// that the playback_handle should no longer be used either because of a
22// hardware/low-level event.
23//
24// When |state_| == kInError, all public API functions will fail with an error
25// (Start() will call the OnError() function on the callback immediately), or
26// no-op themselves with the exception of Close().  Even if an error state has
27// been entered, if Open() has previously returned successfully, Close() must be
28// called to cleanup the ALSA devices and release resources.
29//
30// When |stop_stream_| is set, no more commands will be made against the
31// ALSA device, and playback will effectively stop.  From the client's point of
32// view, it will seem that the device has just clogged and stopped requesting
33// data.
34
35#include "media/audio/alsa/alsa_output.h"
36
37#include <algorithm>
38
39#include "base/bind.h"
40#include "base/debug/trace_event.h"
41#include "base/logging.h"
42#include "base/stl_util.h"
43#include "base/time/time.h"
44#include "media/audio/alsa/alsa_util.h"
45#include "media/audio/alsa/alsa_wrapper.h"
46#include "media/audio/alsa/audio_manager_alsa.h"
47#include "media/base/channel_mixer.h"
48#include "media/base/data_buffer.h"
49#include "media/base/seekable_buffer.h"
50
51namespace media {
52
53// Set to 0 during debugging if you want error messages due to underrun
54// events or other recoverable errors.
55#if defined(NDEBUG)
56static const int kPcmRecoverIsSilent = 1;
57#else
58static const int kPcmRecoverIsSilent = 0;
59#endif
60
61// While the "default" device may support multi-channel audio, in Alsa, only
62// the device names surround40, surround41, surround50, etc, have a defined
63// channel mapping according to Lennart:
64//
65// http://0pointer.de/blog/projects/guide-to-sound-apis.html
66//
67// This function makes a best guess at the specific > 2 channel device name
68// based on the number of channels requested.  NULL is returned if no device
69// can be found to match the channel numbers.  In this case, using
70// kDefaultDevice is probably the best bet.
71//
72// A five channel source is assumed to be surround50 instead of surround41
73// (which is also 5 channels).
74//
75// TODO(ajwong): The source data should have enough info to tell us if we want
76// surround41 versus surround51, etc., instead of needing us to guess based on
77// channel number.  Fix API to pass that data down.
78static const char* GuessSpecificDeviceName(uint32 channels) {
79  switch (channels) {
80    case 8:
81      return "surround71";
82
83    case 7:
84      return "surround70";
85
86    case 6:
87      return "surround51";
88
89    case 5:
90      return "surround50";
91
92    case 4:
93      return "surround40";
94
95    default:
96      return NULL;
97  }
98}
99
100std::ostream& operator<<(std::ostream& os,
101                         AlsaPcmOutputStream::InternalState state) {
102  switch (state) {
103    case AlsaPcmOutputStream::kInError:
104      os << "kInError";
105      break;
106    case AlsaPcmOutputStream::kCreated:
107      os << "kCreated";
108      break;
109    case AlsaPcmOutputStream::kIsOpened:
110      os << "kIsOpened";
111      break;
112    case AlsaPcmOutputStream::kIsPlaying:
113      os << "kIsPlaying";
114      break;
115    case AlsaPcmOutputStream::kIsStopped:
116      os << "kIsStopped";
117      break;
118    case AlsaPcmOutputStream::kIsClosed:
119      os << "kIsClosed";
120      break;
121  };
122  return os;
123}
124
125const char AlsaPcmOutputStream::kDefaultDevice[] = "default";
126const char AlsaPcmOutputStream::kAutoSelectDevice[] = "";
127const char AlsaPcmOutputStream::kPlugPrefix[] = "plug:";
128
129// We use 40ms as our minimum required latency. If it is needed, we may be able
130// to get it down to 20ms.
131const uint32 AlsaPcmOutputStream::kMinLatencyMicros = 40 * 1000;
132
133AlsaPcmOutputStream::AlsaPcmOutputStream(const std::string& device_name,
134                                         const AudioParameters& params,
135                                         AlsaWrapper* wrapper,
136                                         AudioManagerBase* manager)
137    : requested_device_name_(device_name),
138      pcm_format_(alsa_util::BitsToFormat(params.bits_per_sample())),
139      channels_(params.channels()),
140      channel_layout_(params.channel_layout()),
141      sample_rate_(params.sample_rate()),
142      bytes_per_sample_(params.bits_per_sample() / 8),
143      bytes_per_frame_(params.GetBytesPerFrame()),
144      packet_size_(params.GetBytesPerBuffer()),
145      latency_(std::max(
146          base::TimeDelta::FromMicroseconds(kMinLatencyMicros),
147          FramesToTimeDelta(params.frames_per_buffer() * 2, sample_rate_))),
148      bytes_per_output_frame_(bytes_per_frame_),
149      alsa_buffer_frames_(0),
150      stop_stream_(false),
151      wrapper_(wrapper),
152      manager_(manager),
153      message_loop_(base::MessageLoop::current()),
154      playback_handle_(NULL),
155      frames_per_packet_(packet_size_ / bytes_per_frame_),
156      weak_factory_(this),
157      state_(kCreated),
158      volume_(1.0f),
159      source_callback_(NULL),
160      audio_bus_(AudioBus::Create(params)) {
161  DCHECK(manager_->GetTaskRunner()->BelongsToCurrentThread());
162  DCHECK_EQ(audio_bus_->frames() * bytes_per_frame_, packet_size_);
163
164  // Sanity check input values.
165  if (!params.IsValid()) {
166    LOG(WARNING) << "Unsupported audio parameters.";
167    TransitionTo(kInError);
168  }
169
170  if (pcm_format_ == SND_PCM_FORMAT_UNKNOWN) {
171    LOG(WARNING) << "Unsupported bits per sample: " << params.bits_per_sample();
172    TransitionTo(kInError);
173  }
174}
175
176AlsaPcmOutputStream::~AlsaPcmOutputStream() {
177  InternalState current_state = state();
178  DCHECK(current_state == kCreated ||
179         current_state == kIsClosed ||
180         current_state == kInError);
181  DCHECK(!playback_handle_);
182}
183
184bool AlsaPcmOutputStream::Open() {
185  DCHECK(IsOnAudioThread());
186
187  if (state() == kInError)
188    return false;
189
190  if (!CanTransitionTo(kIsOpened)) {
191    NOTREACHED() << "Invalid state: " << state();
192    return false;
193  }
194
195  // We do not need to check if the transition was successful because
196  // CanTransitionTo() was checked above, and it is assumed that this
197  // object's public API is only called on one thread so the state cannot
198  // transition out from under us.
199  TransitionTo(kIsOpened);
200
201  // Try to open the device.
202  if (requested_device_name_ == kAutoSelectDevice) {
203    playback_handle_ = AutoSelectDevice(latency_.InMicroseconds());
204    if (playback_handle_)
205      DVLOG(1) << "Auto-selected device: " << device_name_;
206  } else {
207    device_name_ = requested_device_name_;
208    playback_handle_ = alsa_util::OpenPlaybackDevice(
209        wrapper_, device_name_.c_str(), channels_, sample_rate_,
210        pcm_format_, latency_.InMicroseconds());
211  }
212
213  // Finish initializing the stream if the device was opened successfully.
214  if (playback_handle_ == NULL) {
215    stop_stream_ = true;
216    TransitionTo(kInError);
217    return false;
218  } else {
219    bytes_per_output_frame_ = channel_mixer_ ?
220        mixed_audio_bus_->channels() * bytes_per_sample_ : bytes_per_frame_;
221    uint32 output_packet_size = frames_per_packet_ * bytes_per_output_frame_;
222    buffer_.reset(new media::SeekableBuffer(0, output_packet_size));
223
224    // Get alsa buffer size.
225    snd_pcm_uframes_t buffer_size;
226    snd_pcm_uframes_t period_size;
227    int error = wrapper_->PcmGetParams(playback_handle_, &buffer_size,
228                                       &period_size);
229    if (error < 0) {
230      LOG(ERROR) << "Failed to get playback buffer size from ALSA: "
231                 << wrapper_->StrError(error);
232      // Buffer size is at least twice of packet size.
233      alsa_buffer_frames_ = frames_per_packet_ * 2;
234    } else {
235      alsa_buffer_frames_ = buffer_size;
236    }
237  }
238
239  return true;
240}
241
242void AlsaPcmOutputStream::Close() {
243  DCHECK(IsOnAudioThread());
244
245  if (state() != kIsClosed)
246    TransitionTo(kIsClosed);
247
248  // Shutdown the audio device.
249  if (playback_handle_) {
250    if (alsa_util::CloseDevice(wrapper_, playback_handle_) < 0) {
251      LOG(WARNING) << "Unable to close audio device. Leaking handle.";
252    }
253    playback_handle_ = NULL;
254
255    // Release the buffer.
256    buffer_.reset();
257
258    // Signal anything that might already be scheduled to stop.
259    stop_stream_ = true;  // Not necessary in production, but unit tests
260                          // uses the flag to verify that stream was closed.
261  }
262
263  weak_factory_.InvalidateWeakPtrs();
264
265  // Signal to the manager that we're closed and can be removed.
266  // Should be last call in the method as it deletes "this".
267  manager_->ReleaseOutputStream(this);
268}
269
270void AlsaPcmOutputStream::Start(AudioSourceCallback* callback) {
271  DCHECK(IsOnAudioThread());
272
273  CHECK(callback);
274
275  if (stop_stream_)
276    return;
277
278  // Only post the task if we can enter the playing state.
279  if (TransitionTo(kIsPlaying) != kIsPlaying)
280    return;
281
282  // Before starting, the buffer might have audio from previous user of this
283  // device.
284  buffer_->Clear();
285
286  // When starting again, drop all packets in the device and prepare it again
287  // in case we are restarting from a pause state and need to flush old data.
288  int error = wrapper_->PcmDrop(playback_handle_);
289  if (error < 0 && error != -EAGAIN) {
290    LOG(ERROR) << "Failure clearing playback device ("
291               << wrapper_->PcmName(playback_handle_) << "): "
292               << wrapper_->StrError(error);
293    stop_stream_ = true;
294    return;
295  }
296
297  error = wrapper_->PcmPrepare(playback_handle_);
298  if (error < 0 && error != -EAGAIN) {
299    LOG(ERROR) << "Failure preparing stream ("
300               << wrapper_->PcmName(playback_handle_) << "): "
301               << wrapper_->StrError(error);
302    stop_stream_ = true;
303    return;
304  }
305
306  // Ensure the first buffer is silence to avoid startup glitches.
307  int buffer_size = GetAvailableFrames() * bytes_per_output_frame_;
308  scoped_refptr<DataBuffer> silent_packet = new DataBuffer(buffer_size);
309  silent_packet->set_data_size(buffer_size);
310  memset(silent_packet->writable_data(), 0, silent_packet->data_size());
311  buffer_->Append(silent_packet);
312  WritePacket();
313
314  // Start the callback chain.
315  set_source_callback(callback);
316  WriteTask();
317}
318
319void AlsaPcmOutputStream::Stop() {
320  DCHECK(IsOnAudioThread());
321
322  // Reset the callback, so that it is not called anymore.
323  set_source_callback(NULL);
324  weak_factory_.InvalidateWeakPtrs();
325
326  TransitionTo(kIsStopped);
327}
328
329void AlsaPcmOutputStream::SetVolume(double volume) {
330  DCHECK(IsOnAudioThread());
331
332  volume_ = static_cast<float>(volume);
333}
334
335void AlsaPcmOutputStream::GetVolume(double* volume) {
336  DCHECK(IsOnAudioThread());
337
338  *volume = volume_;
339}
340
341void AlsaPcmOutputStream::BufferPacket(bool* source_exhausted) {
342  DCHECK(IsOnAudioThread());
343
344  // If stopped, simulate a 0-length packet.
345  if (stop_stream_) {
346    buffer_->Clear();
347    *source_exhausted = true;
348    return;
349  }
350
351  *source_exhausted = false;
352
353  // Request more data only when we run out of data in the buffer, because
354  // WritePacket() comsumes only the current chunk of data.
355  if (!buffer_->forward_bytes()) {
356    // Before making a request to source for data we need to determine the
357    // delay (in bytes) for the requested data to be played.
358    const uint32 hardware_delay = GetCurrentDelay() * bytes_per_frame_;
359
360    scoped_refptr<media::DataBuffer> packet =
361        new media::DataBuffer(packet_size_);
362    int frames_filled = RunDataCallback(
363        audio_bus_.get(), AudioBuffersState(0, hardware_delay));
364
365    size_t packet_size = frames_filled * bytes_per_frame_;
366    DCHECK_LE(packet_size, packet_size_);
367
368    // TODO(dalecurtis): Channel downmixing, upmixing, should be done in mixer;
369    // volume adjust should use SSE optimized vector_fmul() prior to interleave.
370    AudioBus* output_bus = audio_bus_.get();
371    if (channel_mixer_) {
372      output_bus = mixed_audio_bus_.get();
373      channel_mixer_->Transform(audio_bus_.get(), output_bus);
374      // Adjust packet size for downmix.
375      packet_size = packet_size / bytes_per_frame_ * bytes_per_output_frame_;
376    }
377
378    // Note: If this ever changes to output raw float the data must be clipped
379    // and sanitized since it may come from an untrusted source such as NaCl.
380    output_bus->Scale(volume_);
381    output_bus->ToInterleaved(
382        frames_filled, bytes_per_sample_, packet->writable_data());
383
384    if (packet_size > 0) {
385      packet->set_data_size(packet_size);
386      // Add the packet to the buffer.
387      buffer_->Append(packet);
388    } else {
389      *source_exhausted = true;
390    }
391  }
392}
393
394void AlsaPcmOutputStream::WritePacket() {
395  DCHECK(IsOnAudioThread());
396
397  // If the device is in error, just eat the bytes.
398  if (stop_stream_) {
399    buffer_->Clear();
400    return;
401  }
402
403  if (state() != kIsPlaying)
404    return;
405
406  CHECK_EQ(buffer_->forward_bytes() % bytes_per_output_frame_, 0u);
407
408  const uint8* buffer_data;
409  int buffer_size;
410  if (buffer_->GetCurrentChunk(&buffer_data, &buffer_size)) {
411    buffer_size = buffer_size - (buffer_size % bytes_per_output_frame_);
412    snd_pcm_sframes_t frames = std::min(
413        static_cast<snd_pcm_sframes_t>(buffer_size / bytes_per_output_frame_),
414        GetAvailableFrames());
415
416    if (!frames)
417      return;
418
419    snd_pcm_sframes_t frames_written =
420        wrapper_->PcmWritei(playback_handle_, buffer_data, frames);
421    if (frames_written < 0) {
422      // Attempt once to immediately recover from EINTR,
423      // EPIPE (overrun/underrun), ESTRPIPE (stream suspended).  WritePacket
424      // will eventually be called again, so eventual recovery will happen if
425      // muliple retries are required.
426      frames_written = wrapper_->PcmRecover(playback_handle_,
427                                            frames_written,
428                                            kPcmRecoverIsSilent);
429      if (frames_written < 0) {
430        if (frames_written != -EAGAIN) {
431          LOG(ERROR) << "Failed to write to pcm device: "
432                     << wrapper_->StrError(frames_written);
433          RunErrorCallback(frames_written);
434          stop_stream_ = true;
435        }
436      }
437    } else {
438      DCHECK_EQ(frames_written, frames);
439
440      // Seek forward in the buffer after we've written some data to ALSA.
441      buffer_->Seek(frames_written * bytes_per_output_frame_);
442    }
443  } else {
444    // If nothing left to write and playback hasn't started yet, start it now.
445    // This ensures that shorter sounds will still play.
446    if (playback_handle_ &&
447        (wrapper_->PcmState(playback_handle_) == SND_PCM_STATE_PREPARED) &&
448        GetCurrentDelay() > 0) {
449      wrapper_->PcmStart(playback_handle_);
450    }
451  }
452}
453
454void AlsaPcmOutputStream::WriteTask() {
455  DCHECK(IsOnAudioThread());
456
457  if (stop_stream_)
458    return;
459
460  if (state() == kIsStopped)
461    return;
462
463  bool source_exhausted;
464  BufferPacket(&source_exhausted);
465  WritePacket();
466
467  ScheduleNextWrite(source_exhausted);
468}
469
470void AlsaPcmOutputStream::ScheduleNextWrite(bool source_exhausted) {
471  DCHECK(IsOnAudioThread());
472
473  if (stop_stream_ || state() != kIsPlaying)
474    return;
475
476  const uint32 kTargetFramesAvailable = alsa_buffer_frames_ / 2;
477  uint32 available_frames = GetAvailableFrames();
478
479  base::TimeDelta next_fill_time;
480  if (buffer_->forward_bytes() && available_frames) {
481    // If we've got data available and ALSA has room, deliver it immediately.
482    next_fill_time = base::TimeDelta();
483  } else if (buffer_->forward_bytes()) {
484    // If we've got data available and no room, poll until room is available.
485    // Polling in this manner allows us to ensure a more consistent callback
486    // schedule.  In testing this yields a variance of +/- 5ms versus the non-
487    // polling strategy which is around +/- 30ms and bimodal.
488    next_fill_time = base::TimeDelta::FromMilliseconds(5);
489  } else if (available_frames < kTargetFramesAvailable) {
490    // Schedule the next write for the moment when the available buffer of the
491    // sound card hits |kTargetFramesAvailable|.
492    next_fill_time = FramesToTimeDelta(
493        kTargetFramesAvailable - available_frames, sample_rate_);
494  } else if (!source_exhausted) {
495    // The sound card has |kTargetFramesAvailable| or more frames available.
496    // Invoke the next write immediately to avoid underrun.
497    next_fill_time = base::TimeDelta();
498  } else {
499    // The sound card has frames available, but our source is exhausted, so
500    // avoid busy looping by delaying a bit.
501    next_fill_time = base::TimeDelta::FromMilliseconds(10);
502  }
503
504  message_loop_->PostDelayedTask(FROM_HERE, base::Bind(
505      &AlsaPcmOutputStream::WriteTask, weak_factory_.GetWeakPtr()),
506      next_fill_time);
507}
508
509// static
510base::TimeDelta AlsaPcmOutputStream::FramesToTimeDelta(int frames,
511                                                       double sample_rate) {
512  return base::TimeDelta::FromMicroseconds(
513      frames * base::Time::kMicrosecondsPerSecond / sample_rate);
514}
515
516std::string AlsaPcmOutputStream::FindDeviceForChannels(uint32 channels) {
517  // Constants specified by the ALSA API for device hints.
518  static const int kGetAllDevices = -1;
519  static const char kPcmInterfaceName[] = "pcm";
520  static const char kIoHintName[] = "IOID";
521  static const char kNameHintName[] = "NAME";
522
523  const char* wanted_device = GuessSpecificDeviceName(channels);
524  if (!wanted_device)
525    return std::string();
526
527  std::string guessed_device;
528  void** hints = NULL;
529  int error = wrapper_->DeviceNameHint(kGetAllDevices,
530                                       kPcmInterfaceName,
531                                       &hints);
532  if (error == 0) {
533    // NOTE: Do not early return from inside this if statement.  The
534    // hints above need to be freed.
535    for (void** hint_iter = hints; *hint_iter != NULL; hint_iter++) {
536      // Only examine devices that are output capable..  Valid values are
537      // "Input", "Output", and NULL which means both input and output.
538      scoped_ptr_malloc<char> io(
539          wrapper_->DeviceNameGetHint(*hint_iter, kIoHintName));
540      if (io != NULL && strcmp(io.get(), "Input") == 0)
541        continue;
542
543      // Attempt to select the closest device for number of channels.
544      scoped_ptr_malloc<char> name(
545          wrapper_->DeviceNameGetHint(*hint_iter, kNameHintName));
546      if (strncmp(wanted_device, name.get(), strlen(wanted_device)) == 0) {
547        guessed_device = name.get();
548        break;
549      }
550    }
551
552    // Destroy the hint now that we're done with it.
553    wrapper_->DeviceNameFreeHint(hints);
554    hints = NULL;
555  } else {
556    LOG(ERROR) << "Unable to get hints for devices: "
557               << wrapper_->StrError(error);
558  }
559
560  return guessed_device;
561}
562
563snd_pcm_sframes_t AlsaPcmOutputStream::GetCurrentDelay() {
564  snd_pcm_sframes_t delay = -1;
565  // Don't query ALSA's delay if we have underrun since it'll be jammed at some
566  // non-zero value and potentially even negative!
567  //
568  // Also, if we're in the prepared state, don't query because that seems to
569  // cause an I/O error when we do query the delay.
570  snd_pcm_state_t pcm_state = wrapper_->PcmState(playback_handle_);
571  if (pcm_state != SND_PCM_STATE_XRUN &&
572      pcm_state != SND_PCM_STATE_PREPARED) {
573    int error = wrapper_->PcmDelay(playback_handle_, &delay);
574    if (error < 0) {
575      // Assume a delay of zero and attempt to recover the device.
576      delay = -1;
577      error = wrapper_->PcmRecover(playback_handle_,
578                                   error,
579                                   kPcmRecoverIsSilent);
580      if (error < 0) {
581        LOG(ERROR) << "Failed querying delay: " << wrapper_->StrError(error);
582      }
583    }
584  }
585
586  // snd_pcm_delay() sometimes returns crazy values.  In this case return delay
587  // of data we know currently is in ALSA's buffer.  Note: When the underlying
588  // driver is PulseAudio based, certain configuration settings (e.g., tsched=1)
589  // will generate much larger delay values than |alsa_buffer_frames_|, so only
590  // clip if delay is truly crazy (> 10x expected).
591  if (static_cast<snd_pcm_uframes_t>(delay) > alsa_buffer_frames_ * 10) {
592    delay = alsa_buffer_frames_ - GetAvailableFrames();
593  }
594
595  if (delay < 0) {
596    delay = 0;
597  }
598
599  return delay;
600}
601
602snd_pcm_sframes_t AlsaPcmOutputStream::GetAvailableFrames() {
603  DCHECK(IsOnAudioThread());
604
605  if (stop_stream_)
606    return 0;
607
608  // Find the number of frames queued in the sound device.
609  snd_pcm_sframes_t available_frames =
610      wrapper_->PcmAvailUpdate(playback_handle_);
611  if (available_frames < 0) {
612    available_frames = wrapper_->PcmRecover(playback_handle_,
613                                            available_frames,
614                                            kPcmRecoverIsSilent);
615  }
616  if (available_frames < 0) {
617    LOG(ERROR) << "Failed querying available frames. Assuming 0: "
618               << wrapper_->StrError(available_frames);
619    return 0;
620  }
621  if (static_cast<uint32>(available_frames) > alsa_buffer_frames_ * 2) {
622    LOG(ERROR) << "ALSA returned " << available_frames << " of "
623               << alsa_buffer_frames_ << " frames available.";
624    return alsa_buffer_frames_;
625  }
626
627  return available_frames;
628}
629
630snd_pcm_t* AlsaPcmOutputStream::AutoSelectDevice(unsigned int latency) {
631  // For auto-selection:
632  //   1) Attempt to open a device that best matches the number of channels
633  //      requested.
634  //   2) If that fails, attempt the "plug:" version of it in case ALSA can
635  //      remap do some software conversion to make it work.
636  //   3) Fallback to kDefaultDevice.
637  //   4) If that fails too, try the "plug:" version of kDefaultDevice.
638  //   5) Give up.
639  snd_pcm_t* handle = NULL;
640  device_name_ = FindDeviceForChannels(channels_);
641
642  // Step 1.
643  if (!device_name_.empty()) {
644    if ((handle = alsa_util::OpenPlaybackDevice(wrapper_, device_name_.c_str(),
645                                                channels_, sample_rate_,
646                                                pcm_format_,
647                                                latency)) != NULL) {
648      return handle;
649    }
650
651    // Step 2.
652    device_name_ = kPlugPrefix + device_name_;
653    if ((handle = alsa_util::OpenPlaybackDevice(wrapper_, device_name_.c_str(),
654                                                channels_, sample_rate_,
655                                                pcm_format_,
656                                                latency)) != NULL) {
657      return handle;
658    }
659  }
660
661  // For the kDefaultDevice device, we can only reliably depend on 2-channel
662  // output to have the correct ordering according to Lennart.  For the channel
663  // formats that we know how to downmix from (3 channel to 8 channel), setup
664  // downmixing.
665  uint32 default_channels = channels_;
666  if (default_channels > 2) {
667    channel_mixer_.reset(new ChannelMixer(
668        channel_layout_, CHANNEL_LAYOUT_STEREO));
669    default_channels = 2;
670    mixed_audio_bus_ = AudioBus::Create(
671        default_channels, audio_bus_->frames());
672  }
673
674  // Step 3.
675  device_name_ = kDefaultDevice;
676  if ((handle = alsa_util::OpenPlaybackDevice(
677      wrapper_, device_name_.c_str(), default_channels, sample_rate_,
678      pcm_format_, latency)) != NULL) {
679    return handle;
680  }
681
682  // Step 4.
683  device_name_ = kPlugPrefix + device_name_;
684  if ((handle = alsa_util::OpenPlaybackDevice(
685      wrapper_, device_name_.c_str(), default_channels, sample_rate_,
686      pcm_format_, latency)) != NULL) {
687    return handle;
688  }
689
690  // Unable to open any device.
691  device_name_.clear();
692  return NULL;
693}
694
695bool AlsaPcmOutputStream::CanTransitionTo(InternalState to) {
696  switch (state_) {
697    case kCreated:
698      return to == kIsOpened || to == kIsClosed || to == kInError;
699
700    case kIsOpened:
701      return to == kIsPlaying || to == kIsStopped ||
702          to == kIsClosed || to == kInError;
703
704    case kIsPlaying:
705      return to == kIsPlaying || to == kIsStopped ||
706          to == kIsClosed || to == kInError;
707
708    case kIsStopped:
709      return to == kIsPlaying || to == kIsStopped ||
710          to == kIsClosed || to == kInError;
711
712    case kInError:
713      return to == kIsClosed || to == kInError;
714
715    case kIsClosed:
716    default:
717      return false;
718  }
719}
720
721AlsaPcmOutputStream::InternalState
722AlsaPcmOutputStream::TransitionTo(InternalState to) {
723  DCHECK(IsOnAudioThread());
724
725  if (!CanTransitionTo(to)) {
726    NOTREACHED() << "Cannot transition from: " << state_ << " to: " << to;
727    state_ = kInError;
728  } else {
729    state_ = to;
730  }
731  return state_;
732}
733
734AlsaPcmOutputStream::InternalState AlsaPcmOutputStream::state() {
735  return state_;
736}
737
738bool AlsaPcmOutputStream::IsOnAudioThread() const {
739  return message_loop_ && message_loop_ == base::MessageLoop::current();
740}
741
742int AlsaPcmOutputStream::RunDataCallback(AudioBus* audio_bus,
743                                         AudioBuffersState buffers_state) {
744  TRACE_EVENT0("audio", "AlsaPcmOutputStream::RunDataCallback");
745
746  if (source_callback_)
747    return source_callback_->OnMoreData(audio_bus, buffers_state);
748
749  return 0;
750}
751
752void AlsaPcmOutputStream::RunErrorCallback(int code) {
753  if (source_callback_)
754    source_callback_->OnError(this);
755}
756
757// Changes the AudioSourceCallback to proxy calls to.  Pass in NULL to
758// release ownership of the currently registered callback.
759void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) {
760  DCHECK(IsOnAudioThread());
761  source_callback_ = callback;
762}
763
764}  // namespace media
765