Home | History | Annotate | Download | only in alsa
      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 
     51 namespace 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)
     56 static const int kPcmRecoverIsSilent = 1;
     57 #else
     58 static 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.
     78 static 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 
    100 std::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 
    125 const char AlsaPcmOutputStream::kDefaultDevice[] = "default";
    126 const char AlsaPcmOutputStream::kAutoSelectDevice[] = "";
    127 const 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.
    131 const uint32 AlsaPcmOutputStream::kMinLatencyMicros = 40 * 1000;
    132 
    133 AlsaPcmOutputStream::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       state_(kCreated),
    157       volume_(1.0f),
    158       source_callback_(NULL),
    159       audio_bus_(AudioBus::Create(params)),
    160       weak_factory_(this) {
    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 
    176 AlsaPcmOutputStream::~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 
    184 bool 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 
    242 void 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 
    270 void 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 
    319 void 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 
    329 void AlsaPcmOutputStream::SetVolume(double volume) {
    330   DCHECK(IsOnAudioThread());
    331 
    332   volume_ = static_cast<float>(volume);
    333 }
    334 
    335 void AlsaPcmOutputStream::GetVolume(double* volume) {
    336   DCHECK(IsOnAudioThread());
    337 
    338   *volume = volume_;
    339 }
    340 
    341 void 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 
    394 void 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 
    454 void 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 
    470 void 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
    510 base::TimeDelta AlsaPcmOutputStream::FramesToTimeDelta(int frames,
    511                                                        double sample_rate) {
    512   return base::TimeDelta::FromMicroseconds(
    513       frames * base::Time::kMicrosecondsPerSecond / sample_rate);
    514 }
    515 
    516 std::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<char, base::FreeDeleter> 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<char, base::FreeDeleter> 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 
    563 snd_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 
    602 snd_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 
    630 snd_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 
    695 bool 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 
    721 AlsaPcmOutputStream::InternalState
    722 AlsaPcmOutputStream::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 
    734 AlsaPcmOutputStream::InternalState AlsaPcmOutputStream::state() {
    735   return state_;
    736 }
    737 
    738 bool AlsaPcmOutputStream::IsOnAudioThread() const {
    739   return message_loop_ && message_loop_ == base::MessageLoop::current();
    740 }
    741 
    742 int 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 
    752 void 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.
    759 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) {
    760   DCHECK(IsOnAudioThread());
    761   source_callback_ = callback;
    762 }
    763 
    764 }  // namespace media
    765