FreeBSD Bugzilla – Attachment 183744 Details for
Bug 220230
www/iridium: add sndio backend
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
iridium.diff
iridium.diff (text/plain), 31.78 KB, created by
Tobias Kortkamp
on 2017-06-23 19:46:23 UTC
(
hide
)
Description:
iridium.diff
Filename:
MIME Type:
Creator:
Tobias Kortkamp
Created:
2017-06-23 19:46:23 UTC
Size:
31.78 KB
patch
obsolete
>Index: Makefile >=================================================================== >--- Makefile (revision 444188) >+++ Makefile (working copy) >@@ -104,7 +104,7 @@ > OPTIONS_DEFINE= CODECS DEBUG GCONF KERBEROS > CODECS_DESC= Compile and enable patented codecs like H.264 > OPTIONS_GROUP= AUDIO >-OPTIONS_GROUP_AUDIO= ALSA PULSEAUDIO >+OPTIONS_GROUP_AUDIO= ALSA PULSEAUDIO SNDIO > > OPTIONS_DEFAULT= ALSA CODECS GCONF KERBEROS > OPTIONS_SUB= yes >@@ -114,6 +114,14 @@ > ALSA_RUN_DEPENDS= ${LOCALBASE}/lib/alsa-lib/libasound_module_pcm_oss.so:audio/alsa-plugins \ > alsa-lib>=1.1.1_1:audio/alsa-lib > PULSEAUDIO_LIB_DEPENDS= libpulse.so:audio/pulseaudio >+# With SNDIO=on we exclude audio_manager_linux from the build (see >+# media/audio/BUILD.gn) and use audio_manager_openbsd which does not >+# support falling back to ALSA. In theory it supports falling back to >+# PulseAudio, but this is untested. >+SNDIO_PREVENTS= ALSA PULSEAUDIO >+SNDIO_LIB_DEPENDS= libsndio.so:audio/sndio >+SNDIO_VARS= GN_ARGS+=use_sndio=true >+SNDIO_VARS_OFF= GN_ARGS+=use_sndio=false > > .include <bsd.port.options.mk> > >@@ -192,6 +200,12 @@ > .endif > @${ECHO_MSG} > >+post-patch-SNDIO-on: >+ @${MKDIR} ${WRKSRC}/media/audio/sndio ${WRKSRC}/media/audio/openbsd >+ @${CP} ${FILESDIR}/sndio_output.* ${WRKSRC}/media/audio/sndio >+ @${CP} ${FILESDIR}/sndio_input.* ${WRKSRC}/media/audio/sndio >+ @${CP} ${FILESDIR}/audio_manager_openbsd.* ${WRKSRC}/media/audio/openbsd >+ > pre-configure: > # We used to remove bundled libraries to be sure that iridium uses > # system libraries and not shippen ones. >Index: files/audio_manager_openbsd.cc >=================================================================== >--- files/audio_manager_openbsd.cc (nonexistent) >+++ files/audio_manager_openbsd.cc (working copy) >@@ -0,0 +1,205 @@ >+// Copyright (c) 2012 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 "base/metrics/histogram_macros.h" >+ >+#include "media/audio/openbsd/audio_manager_openbsd.h" >+ >+#include "media/audio/audio_device_description.h" >+#include "media/audio/audio_output_dispatcher.h" >+#if defined(USE_PULSEAUDIO) >+#include "media/audio/pulse/audio_manager_pulse.h" >+#endif >+#if defined(USE_SNDIO) >+#include "media/audio/sndio/sndio_input.h" >+#include "media/audio/sndio/sndio_output.h" >+#else >+#include "media/audio/fake_audio_manager.h" >+#endif >+#include "media/base/limits.h" >+#include "media/base/media_switches.h" >+ >+namespace media { >+ >+enum OpenBSDAudioIO { >+ kPulse, >+ kSndio, >+ kAudioIOMax = kSndio >+}; >+ >+#if defined(USE_SNDIO) >+// Maximum number of output streams that can be open simultaneously. >+static const int kMaxOutputStreams = 4; >+ >+// Default sample rate for input and output streams. >+static const int kDefaultSampleRate = 48000; >+ >+void AddDefaultDevice(AudioDeviceNames* device_names) { >+ DCHECK(device_names->empty()); >+ device_names->push_front(AudioDeviceName::CreateDefault()); >+} >+ >+bool AudioManagerOpenBSD::HasAudioOutputDevices() { >+ return true; >+} >+ >+bool AudioManagerOpenBSD::HasAudioInputDevices() { >+ return true; >+} >+ >+void AudioManagerOpenBSD::ShowAudioInputSettings() { >+ NOTIMPLEMENTED(); >+} >+ >+void AudioManagerOpenBSD::GetAudioInputDeviceNames( >+ AudioDeviceNames* device_names) { >+ DCHECK(device_names->empty()); >+ AddDefaultDevice(device_names); >+} >+ >+void AudioManagerOpenBSD::GetAudioOutputDeviceNames( >+ AudioDeviceNames* device_names) { >+ AddDefaultDevice(device_names); >+} >+ >+#if defined(USE_SNDIO) >+const char* AudioManagerOpenBSD::GetName() { >+ return "SNDIO"; >+} >+#endif >+ >+AudioParameters AudioManagerOpenBSD::GetInputStreamParameters( >+ const std::string& device_id) { >+ static const int kDefaultInputBufferSize = 1024; >+ >+ int user_buffer_size = GetUserBufferSize(); >+ int buffer_size = user_buffer_size ? >+ user_buffer_size : kDefaultInputBufferSize; >+ >+ return AudioParameters( >+ AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, >+ kDefaultSampleRate, 16, buffer_size); >+} >+ >+AudioManagerOpenBSD::AudioManagerOpenBSD( >+ scoped_refptr<base::SingleThreadTaskRunner> task_runner, >+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, >+ AudioLogFactory* audio_log_factory) >+ : AudioManagerBase(std::move(task_runner), >+ std::move(worker_task_runner), >+ audio_log_factory) { >+ DLOG(WARNING) << "AudioManagerOpenBSD"; >+ SetMaxOutputStreamsAllowed(kMaxOutputStreams); >+} >+ >+AudioManagerOpenBSD::~AudioManagerOpenBSD() { >+ Shutdown(); >+} >+ >+AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream( >+ const AudioParameters& params, >+ const LogCallback& log_callback) { >+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); >+ return MakeOutputStream(params); >+} >+ >+AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream( >+ const AudioParameters& params, >+ const std::string& device_id, >+ const LogCallback& log_callback) { >+ DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; >+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); >+ return MakeOutputStream(params); >+} >+ >+AudioInputStream* AudioManagerOpenBSD::MakeLinearInputStream( >+ const AudioParameters& params, >+ const std::string& device_id, >+ const LogCallback& log_callback) { >+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); >+ return MakeInputStream(params); >+} >+ >+AudioInputStream* AudioManagerOpenBSD::MakeLowLatencyInputStream( >+ const AudioParameters& params, >+ const std::string& device_id, >+ const LogCallback& log_callback) { >+ DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); >+ return MakeInputStream(params); >+} >+ >+AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters( >+ const std::string& output_device_id, >+ const AudioParameters& input_params) { >+ // TODO(tommi): Support |output_device_id|. >+ DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!"; >+ static const int kDefaultOutputBufferSize = 2048; >+ >+ ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO; >+ int sample_rate = kDefaultSampleRate; >+ int buffer_size = kDefaultOutputBufferSize; >+ int bits_per_sample = 16; >+ if (input_params.IsValid()) { >+ sample_rate = input_params.sample_rate(); >+ bits_per_sample = input_params.bits_per_sample(); >+ channel_layout = input_params.channel_layout(); >+ buffer_size = std::min(buffer_size, input_params.frames_per_buffer()); >+ } >+ >+ int user_buffer_size = GetUserBufferSize(); >+ if (user_buffer_size) >+ buffer_size = user_buffer_size; >+ >+ return AudioParameters( >+ AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, >+ sample_rate, bits_per_sample, buffer_size); >+} >+ >+AudioInputStream* AudioManagerOpenBSD::MakeInputStream( >+ const AudioParameters& params) { >+ DLOG(WARNING) << "MakeInputStream"; >+ return new SndioAudioInputStream(this, >+ AudioDeviceDescription::kDefaultDeviceId, params); >+} >+ >+AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream( >+ const AudioParameters& params) { >+ DLOG(WARNING) << "MakeOutputStream"; >+ return new SndioAudioOutputStream(params, this); >+} >+#endif >+ >+ScopedAudioManagerPtr CreateAudioManager( >+ scoped_refptr<base::SingleThreadTaskRunner> task_runner, >+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, >+ AudioLogFactory* audio_log_factory) { >+ DLOG(WARNING) << "CreateAudioManager"; >+#if defined(USE_PULSEAUDIO) >+ // Do not move task runners when creating AudioManagerPulse. >+ // If the creation fails, we need to use the task runners to create other >+ // AudioManager implementations. >+ std::unique_ptr<AudioManagerPulse, AudioManagerDeleter> manager( >+ new AudioManagerPulse(task_runner, worker_task_runner, >+ audio_log_factory)); >+ if (manager->Init()) { >+ UMA_HISTOGRAM_ENUMERATION("Media.OpenBSDAudioIO", kPulse, kAudioIOMax + 1); >+ return std::move(manager); >+ } >+ DVLOG(1) << "PulseAudio is not available on the OS"; >+#endif >+ >+#if defined(USE_SNDIO) >+ UMA_HISTOGRAM_ENUMERATION("Media.OpenBSDAudioIO", kSndio, kAudioIOMax + 1); >+ return ScopedAudioManagerPtr( >+ new AudioManagerOpenBSD(std::move(task_runner), >+ std::move(worker_task_runner),audio_log_factory)); >+#else >+ return ScopedAudioManagerPtr( >+ new FakeAudioManager(std::move(task_runner), >+ std::move(worker_task_runner), audio_log_factory)); >+#endif >+ >+} >+ >+} // namespace media >Index: files/audio_manager_openbsd.h >=================================================================== >--- files/audio_manager_openbsd.h (nonexistent) >+++ files/audio_manager_openbsd.h (working copy) >@@ -0,0 +1,69 @@ >+// Copyright (c) 2012 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. >+ >+#ifndef MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_ >+#define MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_ >+ >+#include <set> >+ >+#include "base/compiler_specific.h" >+#include "base/macros.h" >+#include "base/memory/ref_counted.h" >+#include "base/threading/thread.h" >+#include "media/audio/audio_manager_base.h" >+ >+namespace media { >+ >+class MEDIA_EXPORT AudioManagerOpenBSD : public AudioManagerBase { >+ public: >+ AudioManagerOpenBSD( >+ scoped_refptr<base::SingleThreadTaskRunner> task_runner, >+ scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner, >+ AudioLogFactory* audio_log_factory); >+ >+ // Implementation of AudioManager. >+ bool HasAudioOutputDevices() override; >+ bool HasAudioInputDevices() override; >+ void ShowAudioInputSettings() override; >+ void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override; >+ void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; >+ AudioParameters GetInputStreamParameters( >+ const std::string& device_id) override; >+ const char* GetName() override; >+ >+ // Implementation of AudioManagerBase. >+ AudioOutputStream* MakeLinearOutputStream( >+ const AudioParameters& params, >+ const LogCallback& log_callback) override; >+ AudioOutputStream* MakeLowLatencyOutputStream( >+ const AudioParameters& params, >+ const std::string& device_id, >+ const LogCallback& log_callback) override; >+ AudioInputStream* MakeLinearInputStream( >+ const AudioParameters& params, >+ const std::string& device_id, >+ const LogCallback& log_callback) override; >+ AudioInputStream* MakeLowLatencyInputStream( >+ const AudioParameters& params, >+ const std::string& device_id, >+ const LogCallback& log_callback) override; >+ >+ protected: >+ ~AudioManagerOpenBSD() override; >+ >+ AudioParameters GetPreferredOutputStreamParameters( >+ const std::string& output_device_id, >+ const AudioParameters& input_params) override; >+ >+ private: >+ // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream. >+ AudioOutputStream* MakeOutputStream(const AudioParameters& params); >+ AudioInputStream* MakeInputStream(const AudioParameters& params); >+ >+ DISALLOW_COPY_AND_ASSIGN(AudioManagerOpenBSD); >+}; >+ >+} // namespace media >+ >+#endif // MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_ >Index: files/patch-media_BUILD.gn >=================================================================== >--- files/patch-media_BUILD.gn (nonexistent) >+++ files/patch-media_BUILD.gn (working copy) >@@ -0,0 +1,13 @@ >+$OpenBSD: patch-media_BUILD_gn,v 1.2 2017/04/28 22:22:36 robert Exp $ >+--- media/BUILD.gn.orig.port Wed Apr 19 21:06:35 2017 >++++ media/BUILD.gn Thu Apr 27 19:56:02 2017 >+@@ -56,6 +56,9 @@ config("media_config") { >+ defines += [ "DLOPEN_PULSEAUDIO" ] >+ } >+ } >++ if (use_sndio) { >++ defines += [ "USE_SNDIO" ] >++ } >+ if (use_cras) { >+ defines += [ "USE_CRAS" ] >+ } >Index: files/patch-media_audio_BUILD.gn >=================================================================== >--- files/patch-media_audio_BUILD.gn (revision 444188) >+++ files/patch-media_audio_BUILD.gn (working copy) >@@ -1,14 +1,26 @@ > --- media/audio/BUILD.gn.orig 2017-04-19 19:06:35 UTC > +++ media/audio/BUILD.gn >-@@ -212,7 +212,7 @@ source_set("audio") { >+@@ -212,9 +212,19 @@ source_set("audio") { > deps += [ "//media/base/android:media_jni_headers" ] > } > > - if (is_linux) { >-+ if (is_linux || is_bsd) { >++ if (is_linux || (is_bsd && !use_sndio)) { > sources += [ "linux/audio_manager_linux.cc" ] > } >++ if (use_sndio) { >++ libs += [ "sndio" ] >++ sources += [ >++ "openbsd/audio_manager_openbsd.cc", >++ "sndio/sndio_input.cc", >++ "sndio/sndio_input.h", >++ "sndio/sndio_output.cc", >++ "sndio/sndio_output.h" >++ ] >++ } > >+ if (use_alsa) { >+ libs += [ "asound" ] > @@ -261,10 +261,12 @@ source_set("audio") { > configs += [ ":libpulse" ] > } else { >Index: files/patch-media_media_options.gni >=================================================================== >--- files/patch-media_media_options.gni (nonexistent) >+++ files/patch-media_media_options.gni (working copy) >@@ -0,0 +1,13 @@ >+$OpenBSD: patch-media_media_options_gni,v 1.3 2017/04/28 22:22:36 robert Exp $ >+--- media/media_options.gni.orig 2017-04-19 21:06:35.000000000 +0200 >++++ media/media_options.gni 2017-05-06 22:11:03.288488000 +0200 >+@@ -73,6 +73,9 @@ >+ # Enables runtime selection of ALSA library for audio. >+ use_alsa = false >+ >++ # Enable runtime selection of sndio(7) >++ use_sndio = false >++ >+ # Alsa should be used on non-Android, non-Mac POSIX systems. >+ # Alsa should be used on desktop Chromecast and audio-only Chromecast builds. >+ if (is_posix && !is_android && !is_mac && >Index: files/sndio_input.cc >=================================================================== >--- files/sndio_input.cc (nonexistent) >+++ files/sndio_input.cc (working copy) >@@ -0,0 +1,190 @@ >+// 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 >Index: files/sndio_input.h >=================================================================== >--- files/sndio_input.h (nonexistent) >+++ files/sndio_input.h (working copy) >@@ -0,0 +1,108 @@ >+// 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. >+ >+#ifndef MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_ >+#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_ >+ >+#include <stdint.h> >+#include <string> >+#include <sndio.h> >+ >+#include "base/compiler_specific.h" >+#include "base/macros.h" >+#include "base/memory/weak_ptr.h" >+#include "base/time/time.h" >+#include "media/audio/agc_audio_stream.h" >+#include "media/audio/audio_io.h" >+#include "media/audio/audio_device_description.h" >+#include "media/base/audio_parameters.h" >+ >+namespace media { >+ >+class AudioManagerBase; >+ >+// call-backs invoked from C libraries, thus requiring C linkage >+extern "C" { >+ // Invoked (on the real-time thread) at each sound card clock tick >+ void sndio_in_onmove(void *arg, int delta); >+ // Invoked (on the real-time thread) whenever the volume changes >+ void sndio_in_onvol(void *arg, unsigned int vol); >+ // Real-time thread entry point >+ void *sndio_in_threadstart(void *arg); >+} >+ >+// Provides an input stream for audio capture based on the SNDIO PCM interface. >+// This object is not thread safe and all methods should be invoked in the >+// thread that created the object. >+class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> { >+ public: >+ // Pass this to the constructor if you want to attempt auto-selection >+ // of the audio recording device. >+ static const char kAutoSelectDevice[]; >+ >+ // Create a PCM Output stream for the SNDIO device identified by >+ // |device_name|. If unsure of what to use for |device_name|, use >+ // |kAutoSelectDevice|. >+ SndioAudioInputStream(AudioManagerBase* audio_manager, >+ const std::string& device_name, >+ const AudioParameters& params); >+ >+ ~SndioAudioInputStream() override; >+ >+ // Implementation of AudioInputStream. >+ bool Open() override; >+ void Start(AudioInputCallback* callback) override; >+ void Stop() override; >+ void Close() override; >+ double GetMaxVolume() override; >+ void SetVolume(double volume) override; >+ double GetVolume() override; >+ bool IsMuted() override; >+ >+ // C-linkage call-backs are friends to access private data >+ friend void sndio_in_onmove(void *arg, int delta); >+ friend void sndio_in_onvol(void *arg, unsigned int vol); >+ friend void *sndio_in_threadstart(void *arg); >+ >+ private: >+ // Logs the error and invokes any registered callbacks. >+ void HandleError(const char* method, int error); >+ >+ // Reads one or more buffers of audio from the device, passes on to the >+ // registered callback and schedules the next read. >+ void ReadAudio(); >+ >+ // Recovers from any device errors if possible. >+ bool Recover(int error); >+ >+ // Non-refcounted pointer back to the audio manager. >+ // The AudioManager indirectly holds on to stream objects, so we don't >+ // want circular references. Additionally, stream objects live on the audio >+ // thread, which is owned by the audio manager and we don't want to addref >+ // the manager from that thread. >+ AudioManagerBase* audio_manager_; >+ std::string device_name_; >+ AudioParameters params_; >+ int bytes_per_buffer_; >+ base::TimeDelta buffer_duration_; // Length of each recorded buffer. >+ AudioInputCallback* callback_; // Valid during a recording session. >+ base::TimeTicks next_read_time_; // Scheduled time for next read callback. >+ struct sio_hdl* device_handle_; // Handle to the SNDIO PCM recording device. >+ std::unique_ptr<uint8_t[]> audio_buffer_; // Buffer used for reading audio data. >+ bool read_callback_behind_schedule_; >+ std::unique_ptr<AudioBus> audio_bus_; >+ >+ int hw_delay_; >+ int sndio_rec_bufsize_; >+ int sndio_rec_bufsz_; >+ >+ // High priority thread running RealTimeThread() >+ pthread_t thread_; >+ >+ DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream); >+}; >+ >+} // namespace media >+ >+#endif // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_ >Index: files/sndio_output.cc >=================================================================== >--- files/sndio_output.cc (nonexistent) >+++ files/sndio_output.cc (working copy) >@@ -0,0 +1,177 @@ >+// Copyright (c) 2012 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 "base/logging.h" >+#include "base/time/time.h" >+#include "base/time/default_tick_clock.h" >+#include "media/audio/audio_manager_base.h" >+#include "media/base/audio_timestamp_helper.h" >+#include "media/audio/sndio/sndio_output.h" >+ >+namespace media { >+ >+void sndio_onmove(void *arg, int delta) { >+ SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg); >+ >+ self->hw_delay = delta; >+} >+ >+void sndio_onvol(void *arg, unsigned int vol) { >+ SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg); >+ >+ self->vol = vol; >+} >+ >+void *sndio_threadstart(void *arg) { >+ SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg); >+ >+ self->RealTimeThread(); >+ return NULL; >+} >+ >+SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params, >+ AudioManagerBase* manager) >+ : manager(manager), >+ params(params), >+ audio_bus(AudioBus::Create(params)), >+ bytes_per_frame(params.GetBytesPerFrame()), >+ state(kClosed), >+ mutex(PTHREAD_MUTEX_INITIALIZER) { >+} >+ >+SndioAudioOutputStream::~SndioAudioOutputStream() { >+ if (state != kClosed) >+ Close(); >+} >+ >+bool SndioAudioOutputStream::Open() { >+ struct sio_par par; >+ int sig; >+ >+ 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(); >+ >+ hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0); >+ if (hdl == NULL) { >+ LOG(ERROR) << "Couldn't open audio device."; >+ return false; >+ } >+ 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)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; >+ } >+ state = kStopped; >+ volpending = 0; >+ vol = 0; >+ buffer = new char[audio_bus->frames() * params.GetBytesPerFrame()]; >+ sio_onmove(hdl, sndio_onmove, this); >+ sio_onvol(hdl, sndio_onvol, this); >+ return true; >+ bad_close: >+ sio_close(hdl); >+ return false; >+} >+ >+void SndioAudioOutputStream::Close() { >+ if (state == kClosed) >+ return; >+ if (state == kRunning) >+ Stop(); >+ state = kClosed; >+ delete [] buffer; >+ sio_close(hdl); >+ manager->ReleaseOutputStream(this); // Calls the destructor >+} >+ >+void SndioAudioOutputStream::Start(AudioSourceCallback* callback) { >+ state = kRunning; >+ hw_delay = 0; >+ source = callback; >+ sio_start(hdl); >+ if (pthread_create(&thread, NULL, sndio_threadstart, this) != 0) { >+ LOG(ERROR) << "Failed to create real-time thread."; >+ sio_stop(hdl); >+ state = kStopped; >+ } >+} >+ >+void SndioAudioOutputStream::Stop() { >+ if (state == kStopped) >+ return; >+ state = kStopWait; >+ pthread_join(thread, NULL); >+ sio_stop(hdl); >+ state = kStopped; >+} >+ >+void SndioAudioOutputStream::SetVolume(double v) { >+ pthread_mutex_lock(&mutex); >+ vol = v * SIO_MAXVOL; >+ volpending = 1; >+ pthread_mutex_unlock(&mutex); >+} >+ >+void SndioAudioOutputStream::GetVolume(double* v) { >+ pthread_mutex_lock(&mutex); >+ *v = vol * (1. / SIO_MAXVOL); >+ pthread_mutex_unlock(&mutex); >+} >+ >+void SndioAudioOutputStream::RealTimeThread(void) { >+ int avail, count; >+ >+ while (state == kRunning) { >+ // Update volume if needed >+ pthread_mutex_lock(&mutex); >+ if (volpending) { >+ volpending = 0; >+ sio_setvol(hdl, vol); >+ } >+ pthread_mutex_unlock(&mutex); >+ >+ // Get data to play >+ const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay, params.sample_rate() * 1000); >+ count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get()); >+ audio_bus->ToInterleaved(count, params.bits_per_sample() / 8, buffer); >+ if (count == 0) { >+ // We have to submit something to the device >+ count = audio_bus->frames(); >+ memset(buffer, 0, count * params.GetBytesPerFrame()); >+ LOG(WARNING) << "No data to play, running empty cycle."; >+ } >+ >+ // Submit data to the device >+ avail = count * params.GetBytesPerFrame(); >+ count = sio_write(hdl, buffer, avail); >+ if (count == 0) { >+ LOG(WARNING) << "Audio device disconnected."; >+ break; >+ } >+ >+ // Update hardware pointer >+ hw_delay += count; >+ } >+} >+ >+} // namespace media >Index: files/sndio_output.h >=================================================================== >--- files/sndio_output.h (nonexistent) >+++ files/sndio_output.h (working copy) >@@ -0,0 +1,92 @@ >+// Copyright (c) 2012 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. >+ >+#ifndef MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_ >+#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_ >+ >+#include <pthread.h> >+#include <sndio.h> >+ >+#include "base/time/tick_clock.h" >+#include "base/time/time.h" >+#include "media/audio/audio_io.h" >+ >+ >+namespace media { >+ >+class AudioParameters; >+class AudioManagerBase; >+ >+// call-backs invoked from C libraries, thus requiring C linkage >+extern "C" { >+ // Invoked (on the real-time thread) at each sound card clock tick >+ void sndio_onmove(void *arg, int delta); >+ // Invoked (on the real-time thread) whenever the volume changes >+ void sndio_onvol(void *arg, unsigned int vol); >+ // Real-time thread entry point >+ void *sndio_threadstart(void *arg); >+} >+ >+// Implementation of AudioOutputStream using sndio(7) >+class SndioAudioOutputStream : public AudioOutputStream { >+ public: >+ // The manager is creating this object >+ SndioAudioOutputStream(const AudioParameters& params, >+ AudioManagerBase* manager); >+ virtual ~SndioAudioOutputStream(); >+ >+ // Implementation of AudioOutputStream. >+ virtual bool Open() override; >+ virtual void Close() override; >+ virtual void Start(AudioSourceCallback* callback) override; >+ virtual void Stop() override; >+ virtual void SetVolume(double volume) override; >+ virtual void GetVolume(double* volume) override; >+ >+ // C-linkage call-backs are friends to access private data >+ friend void sndio_onmove(void *arg, int delta); >+ friend void sndio_onvol(void *arg, unsigned int vol); >+ friend void *sndio_threadstart(void *arg); >+ >+ private: >+ enum StreamState { >+ kClosed, // Not opened yet >+ kStopped, // Device opened, but not started yet >+ kRunning, // Started, device playing >+ kStopWait // Stopping, waiting for the real-time thread to exit >+ }; >+ // Continuously moves data from the audio bus to the device >+ void RealTimeThread(void); >+ // Our creator, the audio manager needs to be notified when we close. >+ AudioManagerBase* manager; >+ // Parameters of the source >+ AudioParameters params; >+ // Source stores data here >+ std::unique_ptr<AudioBus> audio_bus; >+ int bytes_per_frame; >+ // Call-back that produces data to play >+ AudioSourceCallback* source; >+ // Handle of the audio device >+ struct sio_hdl* hdl; >+ // Current state of the stream >+ enum StreamState state; >+ // High priority thread running RealTimeThread() >+ pthread_t thread; >+ // Protects vol, volpending and hw_delay >+ pthread_mutex_t mutex; >+ // Current volume in the 0..SIO_MAXVOL range >+ int vol; >+ // Set to 1 if volumes must be refreshed in the realtime thread >+ int volpending; >+ // Number of bytes buffered in the hardware >+ int hw_delay; >+ // Temporary buffer where data is stored sndio-compatible format >+ char* buffer; >+ >+ DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream); >+}; >+ >+} // namespace media >+ >+#endif // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
cpm
:
maintainer-approval+
Actions:
View
|
Diff
Attachments on
bug 220230
: 183744 |
183745