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/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 
     52 namespace 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)
     57 static const int kPcmRecoverIsSilent = 1;
     58 #else
     59 static 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.
     79 static 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 
    101 std::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 
    126 const char AlsaPcmOutputStream::kDefaultDevice[] = "default";
    127 const char AlsaPcmOutputStream::kAutoSelectDevice[] = "";
    128 const 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.
    132 const uint32 AlsaPcmOutputStream::kMinLatencyMicros = 40 * 1000;
    133 
    134 AlsaPcmOutputStream::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 
    177 AlsaPcmOutputStream::~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 
    185 bool 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 
    243 void 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 
    271 void 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 
    320 void 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 
    330 void AlsaPcmOutputStream::SetVolume(double volume) {
    331   DCHECK(IsOnAudioThread());
    332 
    333   volume_ = static_cast<float>(volume);
    334 }
    335 
    336 void AlsaPcmOutputStream::GetVolume(double* volume) {
    337   DCHECK(IsOnAudioThread());
    338 
    339   *volume = volume_;
    340 }
    341 
    342 void 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 
    395 void 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 
    455 void 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 
    471 void 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
    511 base::TimeDelta AlsaPcmOutputStream::FramesToTimeDelta(int frames,
    512                                                        double sample_rate) {
    513   return base::TimeDelta::FromMicroseconds(
    514       frames * base::Time::kMicrosecondsPerSecond / sample_rate);
    515 }
    516 
    517 std::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 
    564 snd_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 
    603 snd_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 
    631 snd_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 
    696 bool 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 
    722 AlsaPcmOutputStream::InternalState
    723 AlsaPcmOutputStream::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 
    735 AlsaPcmOutputStream::InternalState AlsaPcmOutputStream::state() {
    736   return state_;
    737 }
    738 
    739 bool AlsaPcmOutputStream::IsOnAudioThread() const {
    740   return message_loop_ && message_loop_ == base::MessageLoop::current();
    741 }
    742 
    743 int 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 
    753 void 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.
    760 void AlsaPcmOutputStream::set_source_callback(AudioSourceCallback* callback) {
    761   DCHECK(IsOnAudioThread());
    762   source_callback_ = callback;
    763 }
    764 
    765 }  // namespace media
    766