Changeset View
Changeset View
Standalone View
Standalone View
head/www/qt5-webengine/files/sndio_input.cc
Property | Old Value | New Value |
---|---|---|
fbsd:nokeywords | null | yes \ No newline at end of property |
svn:eol-style | null | native \ No newline at end of property |
svn:mime-type | null | text/plain \ No newline at end of property |
// Copyright 2013 The Chromium Authors. All rights reserved. | |||||
// Use of this source code is governed by a BSD-style license that can be | |||||
// found in the LICENSE file. | |||||
#include "media/audio/sndio/sndio_input.h" | |||||
#include <stddef.h> | |||||
#include "base/bind.h" | |||||
#include "base/logging.h" | |||||
#include "base/macros.h" | |||||
#include "base/message_loop/message_loop.h" | |||||
#include "media/audio/openbsd/audio_manager_openbsd.h" | |||||
#include "media/audio/audio_manager.h" | |||||
namespace media { | |||||
void sndio_in_onmove(void *arg, int delta) { | |||||
NOTIMPLEMENTED(); | |||||
SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg); | |||||
self->hw_delay_ = delta - self->params_.GetBytesPerFrame(); | |||||
} | |||||
void *sndio_in_threadstart(void *arg) { | |||||
NOTIMPLEMENTED(); | |||||
SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg); | |||||
self->ReadAudio(); | |||||
return NULL; | |||||
} | |||||
SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* audio_manager, | |||||
const std::string& device_name, | |||||
const AudioParameters& params) | |||||
: audio_manager_(audio_manager), | |||||
device_name_(device_name), | |||||
params_(params), | |||||
bytes_per_buffer_(params.frames_per_buffer() * | |||||
(params.channels() * params.bits_per_sample()) / | |||||
8), | |||||
buffer_duration_(base::TimeDelta::FromMicroseconds( | |||||
params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond / | |||||
static_cast<float>(params.sample_rate()))), | |||||
callback_(NULL), | |||||
device_handle_(NULL), | |||||
read_callback_behind_schedule_(false), | |||||
audio_bus_(AudioBus::Create(params)) { | |||||
} | |||||
SndioAudioInputStream::~SndioAudioInputStream() {} | |||||
bool SndioAudioInputStream::Open() { | |||||
struct sio_par par; | |||||
int sig; | |||||
if (device_handle_) | |||||
return false; // Already open. | |||||
if (params_.format() != AudioParameters::AUDIO_PCM_LINEAR && | |||||
params_.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) { | |||||
LOG(WARNING) << "Unsupported audio format."; | |||||
return false; | |||||
} | |||||
sio_initpar(&par); | |||||
par.rate = params_.sample_rate(); | |||||
par.pchan = params_.channels(); | |||||
par.bits = params_.bits_per_sample(); | |||||
par.bps = par.bits / 8; | |||||
par.sig = sig = par.bits != 8 ? 1 : 0; | |||||
par.le = SIO_LE_NATIVE; | |||||
par.appbufsz = params_.frames_per_buffer(); | |||||
sndio_rec_bufsz_ = par.bufsz; | |||||
sndio_rec_bufsize_ = par.round * par.bps * par.rchan; | |||||
device_handle_ = sio_open(SIO_DEVANY, SIO_REC, 0); | |||||
if (device_handle_ == NULL) { | |||||
LOG(ERROR) << "Couldn't open audio device."; | |||||
return false; | |||||
} | |||||
if (!sio_setpar(device_handle_, &par) || !sio_getpar(device_handle_, &par)) { | |||||
LOG(ERROR) << "Couldn't set audio parameters."; | |||||
goto bad_close; | |||||
} | |||||
if (par.rate != (unsigned int)params_.sample_rate() || | |||||
par.pchan != (unsigned int)params_.channels() || | |||||
par.bits != (unsigned int)params_.bits_per_sample() || | |||||
par.sig != (unsigned int)sig || | |||||
(par.bps > 1 && par.le != SIO_LE_NATIVE) || | |||||
(par.bits != par.bps * 8)) { | |||||
LOG(ERROR) << "Unsupported audio parameters."; | |||||
goto bad_close; | |||||
} | |||||
sio_onmove(device_handle_, sndio_in_onmove, this); | |||||
audio_buffer_.reset(new uint8_t[bytes_per_buffer_]); | |||||
return true; | |||||
bad_close: | |||||
sio_close(device_handle_); | |||||
return false; | |||||
} | |||||
void SndioAudioInputStream::Start(AudioInputCallback* callback) { | |||||
DCHECK(!callback_ && callback); | |||||
callback_ = callback; | |||||
StartAgc(); | |||||
// We start reading data half |buffer_duration_| later than when the | |||||
// buffer might have got filled, to accommodate some delays in the audio | |||||
// driver. This could also give us a smooth read sequence going forward. | |||||
base::TimeDelta delay = buffer_duration_ + buffer_duration_ / 2; | |||||
next_read_time_ = base::TimeTicks::Now() + delay; | |||||
if (pthread_create(&thread_, NULL, sndio_in_threadstart, this) != 0) | |||||
LOG(ERROR) << "Failed to create real-time thread."; | |||||
} | |||||
void SndioAudioInputStream::ReadAudio() { | |||||
NOTIMPLEMENTED(); | |||||
DCHECK(callback_); | |||||
int num_buffers = sndio_rec_bufsize_ / params_.frames_per_buffer(); | |||||
double normalized_volume = 0.0; | |||||
// Update the AGC volume level once every second. Note that, |volume| is | |||||
// also updated each time SetVolume() is called through IPC by the | |||||
// render-side AGC. | |||||
GetAgcVolume(&normalized_volume); | |||||
while (num_buffers--) { | |||||
int frames_read = sio_read(device_handle_, audio_buffer_.get(), | |||||
params_.frames_per_buffer()); | |||||
if (frames_read == params_.frames_per_buffer()) { | |||||
audio_bus_->FromInterleaved(audio_buffer_.get(), | |||||
audio_bus_->frames(), | |||||
params_.bits_per_sample() / 8); | |||||
callback_->OnData( | |||||
this, audio_bus_.get(), hw_delay_, normalized_volume); | |||||
} else { | |||||
LOG(WARNING) << "sio_read() returning less than expected frames: " | |||||
<< frames_read << " vs. " << params_.frames_per_buffer() | |||||
<< ". Dropping this buffer."; | |||||
} | |||||
} | |||||
} | |||||
void SndioAudioInputStream::Stop() { | |||||
if (!device_handle_ || !callback_) | |||||
return; | |||||
StopAgc(); | |||||
pthread_join(thread_, NULL); | |||||
sio_stop(device_handle_); | |||||
callback_ = NULL; | |||||
} | |||||
void SndioAudioInputStream::Close() { | |||||
if (device_handle_) { | |||||
sio_close(device_handle_); | |||||
audio_buffer_.reset(); | |||||
device_handle_ = NULL; | |||||
} | |||||
audio_manager_->ReleaseInputStream(this); | |||||
} | |||||
double SndioAudioInputStream::GetMaxVolume() { | |||||
return static_cast<double>(SIO_MAXVOL); | |||||
} | |||||
void SndioAudioInputStream::SetVolume(double volume) { | |||||
NOTIMPLEMENTED(); | |||||
} | |||||
double SndioAudioInputStream::GetVolume() { | |||||
long current_volume = 0; | |||||
return static_cast<double>(current_volume); | |||||
} | |||||
bool SndioAudioInputStream::IsMuted() { | |||||
return false; | |||||
} | |||||
} // namespace media |