1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/audio/alsa/alsa_input.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/audio/alsa/alsa_output.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/audio/alsa/alsa_util.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/audio/alsa/alsa_wrapper.h"
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "media/audio/alsa/audio_manager_alsa.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_manager.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kNumPacketsInRingBuffer = 3;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kDefaultDevice1[] = "default";
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kDefaultDevice2[] = "plug:default";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char AlsaPcmInputStream::kAutoSelectDevice[] = "";
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)AlsaPcmInputStream::AlsaPcmInputStream(AudioManagerBase* audio_manager,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const std::string& device_name,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const AudioParameters& params,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       AlsaWrapper* wrapper)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : audio_manager_(audio_manager),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_name_(device_name),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params_(params),
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_per_buffer_(params.frames_per_buffer() *
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                        (params.channels() * params.bits_per_sample()) /
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                        8),
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wrapper_(wrapper),
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      buffer_duration_(base::TimeDelta::FromMicroseconds(
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          static_cast<float>(params.sample_rate()))),
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      callback_(NULL),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_handle_(NULL),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_handle_(NULL),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_element_handle_(NULL),
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      read_callback_behind_schedule_(false),
466d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      audio_bus_(AudioBus::Create(params)),
476d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      weak_factory_(this) {
486d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AlsaPcmInputStream::~AlsaPcmInputStream() {}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AlsaPcmInputStream::Open() {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_handle_)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // Already open.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snd_pcm_format_t pcm_format = alsa_util::BitsToFormat(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params_.bits_per_sample());
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pcm_format == SND_PCM_FORMAT_UNKNOWN) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unsupported bits per sample: "
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << params_.bits_per_sample();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint32 latency_us =
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      buffer_duration_.InMicroseconds() * kNumPacketsInRingBuffer;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use the same minimum required latency as output.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  latency_us = std::max(latency_us, AlsaPcmOutputStream::kMinLatencyMicros);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_name_ == kAutoSelectDevice) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* device_names[] = { kDefaultDevice1, kDefaultDevice2 };
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < arraysize(device_names); ++i) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      device_handle_ = alsa_util::OpenCaptureDevice(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          wrapper_, device_names[i], params_.channels(),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          params_.sample_rate(), pcm_format, latency_us);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (device_handle_) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        device_name_ = device_names[i];
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device_handle_ = alsa_util::OpenCaptureDevice(wrapper_,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  device_name_.c_str(),
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  params_.channels(),
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  params_.sample_rate(),
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                  pcm_format, latency_us);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_handle_) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_buffer_.reset(new uint8[bytes_per_buffer_]);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Open the microphone mixer.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_handle_ = alsa_util::OpenMixer(wrapper_, device_name_);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mixer_handle_) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_element_handle_ = alsa_util::LoadCaptureMixerElement(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          wrapper_, mixer_handle_);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return device_handle_ != NULL;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlsaPcmInputStream::Start(AudioInputCallback* callback) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback_ && callback);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callback_ = callback;
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StartAgc();
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = wrapper_->PcmPrepare(device_handle_);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error < 0) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HandleError("PcmPrepare", error);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = wrapper_->PcmStart(device_handle_);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error < 0)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleError("PcmStart", error);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error < 0) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callback_ = NULL;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We start reading data half |buffer_duration_| later than when the
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buffer might have got filled, to accommodate some delays in the audio
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // driver. This could also give us a smooth read sequence going forward.
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta delay = buffer_duration_ + buffer_duration_ / 2;
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    next_read_time_ = base::TimeTicks::Now() + delay;
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delay);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool AlsaPcmInputStream::Recover(int original_error) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = wrapper_->PcmRecover(device_handle_, original_error, 1);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error < 0) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Docs say snd_pcm_recover returns the original error if it is not one
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of the recoverable ones, so this log message will probably contain the
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // same error twice.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Unable to recover from \""
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << wrapper_->StrError(original_error) << "\": "
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << wrapper_->StrError(error);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (original_error == -EPIPE) {  // Buffer underrun/overrun.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For capture streams we have to repeat the explicit start() to get
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // data flowing again.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error = wrapper_->PcmStart(device_handle_);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error < 0) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleError("PcmStart", error);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)snd_pcm_sframes_t AlsaPcmInputStream::GetCurrentDelay() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snd_pcm_sframes_t delay = -1;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = wrapper_->PcmDelay(device_handle_, &delay);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error < 0)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Recover(error);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // snd_pcm_delay() may not work in the beginning of the stream. In this case
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return delay of data we know currently is in the ALSA's buffer.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delay < 0)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delay = wrapper_->PcmAvailUpdate(device_handle_);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return delay;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlsaPcmInputStream::ReadAudio() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(callback_);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snd_pcm_sframes_t frames = wrapper_->PcmAvailUpdate(device_handle_);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frames < 0) {  // Potentially recoverable error?
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "PcmAvailUpdate(): " << wrapper_->StrError(frames);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Recover(frames);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (frames < params_.frames_per_buffer()) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not enough data yet or error happened. In both cases wait for a very
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // small duration before checking again.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Even Though read callback was behind schedule, there is no data, so
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // reset the next_read_time_.
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (read_callback_behind_schedule_) {
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      next_read_time_ = base::TimeTicks::Now();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_callback_behind_schedule_ = false;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::TimeDelta next_check_time = buffer_duration_ / 2;
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        next_check_time);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_buffers = frames / params_.frames_per_buffer();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 hardware_delay_bytes =
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<uint32>(GetCurrentDelay() * params_.GetBytesPerFrame());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double normalized_volume = 0.0;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the AGC volume level once every second. Note that, |volume| is
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // also updated each time SetVolume() is called through IPC by the
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // render-side AGC.
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GetAgcVolume(&normalized_volume);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (num_buffers--) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int frames_read = wrapper_->PcmReadi(device_handle_, audio_buffer_.get(),
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         params_.frames_per_buffer());
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frames_read == params_.frames_per_buffer()) {
2136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      audio_bus_->FromInterleaved(audio_buffer_.get(),
2146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  audio_bus_->frames(),
2156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                                  params_.bits_per_sample() / 8);
2166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      callback_->OnData(
2176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)          this, audio_bus_.get(), hardware_delay_bytes, normalized_volume);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "PcmReadi returning less than expected frames: "
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << frames_read << " vs. " << params_.frames_per_buffer()
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << ". Dropping this buffer.";
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  next_read_time_ += buffer_duration_;
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::TimeDelta delay = next_read_time_ - base::TimeTicks::Now();
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delay < base::TimeDelta()) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Audio read callback behind schedule by "
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << (buffer_duration_ - delay).InMicroseconds()
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << " (us).";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read callback is behind schedule. Assuming there is data pending in
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the soundcard, invoke the read callback immediate in order to catch up.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_callback_behind_schedule_ = true;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delay = base::TimeDelta();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&AlsaPcmInputStream::ReadAudio, weak_factory_.GetWeakPtr()),
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delay);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlsaPcmInputStream::Stop() {
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!device_handle_ || !callback_)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StopAgc();
24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  weak_factory_.InvalidateWeakPtrs();  // Cancel the next scheduled read.
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = wrapper_->PcmDrop(device_handle_);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error < 0)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HandleError("PcmDrop", error);
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  callback_ = NULL;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlsaPcmInputStream::Close() {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_handle_) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    weak_factory_.InvalidateWeakPtrs();  // Cancel the next scheduled read.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int error = alsa_util::CloseDevice(wrapper_, device_handle_);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error < 0)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleError("PcmClose", error);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (mixer_handle_)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alsa_util::CloseMixer(wrapper_, mixer_handle_, device_name_);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_buffer_.reset();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    device_handle_ = NULL;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_handle_ = NULL;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mixer_element_handle_ = NULL;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_manager_->ReleaseInputStream(this);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double AlsaPcmInputStream::GetMaxVolume() {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mixer_handle_ || !mixer_element_handle_) {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "GetMaxVolume is not supported for " << device_name_;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0.0;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!wrapper_->MixerSelemHasCaptureVolume(mixer_element_handle_)) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Unsupported microphone volume for " << device_name_;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0.0;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  long min = 0;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  long max = 0;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wrapper_->MixerSelemGetCaptureVolumeRange(mixer_element_handle_,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                &min,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                &max)) {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Unsupported max microphone volume for " << device_name_;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0.0;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(min == 0);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(max > 0);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<double>(max);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlsaPcmInputStream::SetVolume(double volume) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mixer_handle_ || !mixer_element_handle_) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "SetVolume is not supported for " << device_name_;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = wrapper_->MixerSelemSetCaptureVolumeAll(
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_element_handle_, static_cast<long>(volume));
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error < 0) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Unable to set volume for " << device_name_;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the AGC volume level based on the last setting above. Note that,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the volume-level resolution is not infinite and it is therefore not
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // possible to assume that the volume provided as input parameter can be
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // used directly. Instead, a new query to the audio hardware is required.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This method does nothing if AGC is disabled.
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateAgcVolume();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)double AlsaPcmInputStream::GetVolume() {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mixer_handle_ || !mixer_element_handle_) {
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "GetVolume is not supported for " << device_name_;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0.0;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  long current_volume = 0;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = wrapper_->MixerSelemGetCaptureVolume(
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      mixer_element_handle_, static_cast<snd_mixer_selem_channel_id_t>(0),
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &current_volume);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error < 0) {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(WARNING) << "Unable to get volume for " << device_name_;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0.0;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<double>(current_volume);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
339ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdochbool AlsaPcmInputStream::IsMuted() {
340ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch  return false;
341ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch}
342ab8f6f0bd665d3c1ff476eb06c58c42630e462d4Ben Murdoch
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AlsaPcmInputStream::HandleError(const char* method, int error) {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(WARNING) << method << ": " << wrapper_->StrError(error);
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_->OnError(this);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
349