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