diff options
author | Carlos J. Puga Medina <cpm@FreeBSD.org> | 2019-07-09 08:20:56 +0000 |
---|---|---|
committer | Carlos J. Puga Medina <cpm@FreeBSD.org> | 2019-07-09 08:20:56 +0000 |
commit | 75d7ca14e96203d14dc058e040c122c65a6420fb (patch) | |
tree | 414adcaa820213a8d951b3395a6c54a967956bdb /www/chromium/files/sndio_input.cc | |
parent | 126d73a99812486445d3e5ebcf302073c9d9b8a6 (diff) | |
download | ports-75d7ca14e96203d14dc058e040c122c65a6420fb.tar.gz ports-75d7ca14e96203d14dc058e040c122c65a6420fb.zip |
Notes
Diffstat (limited to 'www/chromium/files/sndio_input.cc')
-rw-r--r-- | www/chromium/files/sndio_input.cc | 185 |
1 files changed, 108 insertions, 77 deletions
diff --git a/www/chromium/files/sndio_input.cc b/www/chromium/files/sndio_input.cc index 4a00d8ac1083..c4214a5f84ba 100644 --- a/www/chromium/files/sndio_input.cc +++ b/www/chromium/files/sndio_input.cc @@ -2,169 +2,200 @@ // 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/base/audio_timestamp_helper.h" #include "media/audio/openbsd/audio_manager_openbsd.h" #include "media/audio/audio_manager.h" +#include "media/audio/sndio/sndio_input.h" namespace media { static const SampleFormat kSampleFormat = kSampleFormatS16; -void sndio_in_onmove(void *arg, int delta) { - NOTIMPLEMENTED(); +void SndioAudioInputStream::OnMoveCallback(void *arg, int delta) +{ SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg); - self->hw_delay_ = delta - self->params_.GetBytesPerFrame(kSampleFormat); + self->hw_delay += delta; } -void *sndio_in_threadstart(void *arg) { - NOTIMPLEMENTED(); +void *SndioAudioInputStream::ThreadEntry(void *arg) { SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg); - self->ReadAudio(); + self->ThreadLoop(); 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.GetBytesPerBuffer(kSampleFormat)), - 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(AudioManagerBase* manager, + const std::string& device_name, + const AudioParameters& params) + : manager(manager), + params(params), + audio_bus(AudioBus::Create(params)), + state(kClosed) { } -SndioAudioInputStream::~SndioAudioInputStream() {} +SndioAudioInputStream::~SndioAudioInputStream() { + if (state != kClosed) + Close(); +} bool SndioAudioInputStream::Open() { struct sio_par par; int sig; - if (device_handle_) - return false; // Already open. + if (state != kClosed) + return false; - if (params_.format() != AudioParameters::AUDIO_PCM_LINEAR && - params_.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) { + 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 = SampleFormatToBytesPerChannel(kSampleFormat); + par.rate = params.sample_rate(); + par.rchan = params.channels(); + par.bits = SampleFormatToBitsPerChannel(kSampleFormat); 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; + par.appbufsz = params.frames_per_buffer(); - device_handle_ = sio_open(SIO_DEVANY, SIO_REC, 0); + hdl = sio_open(SIO_DEVANY, SIO_REC, 0); - if (device_handle_ == NULL) { + if (hdl == NULL) { LOG(ERROR) << "Couldn't open audio device."; return false; } - if (!sio_setpar(device_handle_, &par) || !sio_getpar(device_handle_, &par)) { + if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &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)SampleFormatToBytesPerChannel(kSampleFormat) || + if (par.rate != (unsigned int)params.sample_rate() || + par.rchan != (unsigned int)params.channels() || + par.bits != (unsigned int)SampleFormatToBitsPerChannel(kSampleFormat) || 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_]); - + state = kStopped; + buffer = new char[audio_bus->frames() * params.GetBytesPerFrame(kSampleFormat)]; + sio_onmove(hdl, &OnMoveCallback, this); return true; bad_close: - sio_close(device_handle_); + sio_close(hdl); return false; } -void SndioAudioInputStream::Start(AudioInputCallback* callback) { - DCHECK(!callback_ && callback); - callback_ = callback; - StartAgc(); +void SndioAudioInputStream::Start(AudioInputCallback* cb) { - // 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."; -} + StartAgc(); -void SndioAudioInputStream::ReadAudio() { - NOTIMPLEMENTED(); + state = kRunning; + hw_delay = 0; + callback = cb; + sio_start(hdl); + if (pthread_create(&thread, NULL, &ThreadEntry, this) != 0) { + LOG(ERROR) << "Failed to create real-time thread for recording."; + sio_stop(hdl); + state = kStopped; + } } void SndioAudioInputStream::Stop() { - if (!device_handle_ || !callback_) - return; - StopAgc(); + if (state == kStopped) + return; - pthread_join(thread_, NULL); - sio_stop(device_handle_); + state = kStopWait; + pthread_join(thread, NULL); + sio_stop(hdl); + state = kStopped; - callback_ = NULL; + StopAgc(); } void SndioAudioInputStream::Close() { - if (device_handle_) { - sio_close(device_handle_); - audio_buffer_.reset(); - device_handle_ = NULL; - } - audio_manager_->ReleaseInputStream(this); + if (state == kClosed) + return; + + if (state == kRunning) + Stop(); + + state = kClosed; + delete [] buffer; + sio_close(hdl); + + manager->ReleaseInputStream(this); } double SndioAudioInputStream::GetMaxVolume() { - return static_cast<double>(SIO_MAXVOL); + // Not supported + return 0.0; } void SndioAudioInputStream::SetVolume(double volume) { - NOTIMPLEMENTED(); + // Not supported. Do nothing. } double SndioAudioInputStream::GetVolume() { - long current_volume = 0; - return static_cast<double>(current_volume); + // Not supported. + return 0.0; } bool SndioAudioInputStream::IsMuted() { + // Not supported. return false; } void SndioAudioInputStream::SetOutputDeviceForAec( const std::string& output_device_id) { -// Not supported. Do nothing. + // Not supported. +} + +void SndioAudioInputStream::ThreadLoop(void) { + size_t todo, n; + char *data; + unsigned int nframes; + double normalized_volume = 0.0; + + nframes = audio_bus->frames(); + + while (state == kRunning && !sio_eof(hdl)) { + + GetAgcVolume(&normalized_volume); + + // read one block + todo = nframes * params.GetBytesPerFrame(kSampleFormat); + data = buffer; + while (todo > 0) { + n = sio_read(hdl, data, todo); + if (n == 0) + return; // unrecoverable I/O error + todo -= n; + data += n; + } + hw_delay -= nframes; + + // convert frames count to TimeDelta + const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay, + params.sample_rate() * 1000); + + // push into bus + audio_bus->FromInterleaved(buffer, nframes, SampleFormatToBytesPerChannel(kSampleFormat)); + + // invoke callback + callback->OnData(audio_bus.get(), base::TimeTicks::Now() - delay, 1.); + } } } // namespace media |