Date: Sun, 22 Jul 2018 04:16:38 +0000 (UTC) From: Tobias Kortkamp <tobik@FreeBSD.org> To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r475084 - in head/www/qt5-webengine: . files Message-ID: <201807220416.w6M4GcSr064977@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tobik Date: Sun Jul 22 04:16:38 2018 New Revision: 475084 URL: https://svnweb.freebsd.org/changeset/ports/475084 Log: www/qt5-webengine: Add sndio support While here fix ALSA and PULSEAUDIO options - With alsa-lib installed in the build environment ALSA=off did not previously disable ALSA support - PulseAudio support was always disabled regardless of option state Approved by: kde (tcberner) Differential Revision: https://reviews.freebsd.org/D16383 Added: head/www/qt5-webengine/files/audio_manager_openbsd.cc - copied, changed from r474875, head/www/iridium/files/audio_manager_openbsd.cc head/www/qt5-webengine/files/audio_manager_openbsd.h - copied, changed from r474875, head/www/iridium/files/audio_manager_openbsd.h head/www/qt5-webengine/files/patch-configure.json (contents, props changed) head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_BUILD.gn (contents, props changed) head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_media__options.gni (contents, props changed) head/www/qt5-webengine/files/patch-src_core_config_linux.pri (contents, props changed) head/www/qt5-webengine/files/sndio_input.cc - copied unchanged from r474875, head/www/iridium/files/sndio_input.cc head/www/qt5-webengine/files/sndio_input.h - copied unchanged from r474875, head/www/iridium/files/sndio_input.h head/www/qt5-webengine/files/sndio_output.cc - copied unchanged from r474875, head/www/iridium/files/sndio_output.cc head/www/qt5-webengine/files/sndio_output.h - copied unchanged from r474875, head/www/iridium/files/sndio_output.h Modified: head/www/qt5-webengine/Makefile head/www/qt5-webengine/files/freebsd.pri head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_audio_BUILD.gn Modified: head/www/qt5-webengine/Makefile ============================================================================== --- head/www/qt5-webengine/Makefile Sun Jul 22 03:22:52 2018 (r475083) +++ head/www/qt5-webengine/Makefile Sun Jul 22 04:16:38 2018 (r475084) @@ -52,15 +52,20 @@ DISTINFO_FILE= ${.CURDIR}/distinfo QT5_VERSION= 5.9.5 OPTIONS_SINGLE= AUDIO -OPTIONS_SINGLE_AUDIO= ALSA PULSEAUDIO +OPTIONS_SINGLE_AUDIO= ALSA PULSEAUDIO SNDIO OPTIONS_DEFAULT= ALSA AUDIO_DESC= Audio backend ALSA_LIB_DEPENDS= libasound.so:audio/alsa-lib -ALSA_QMAKE_ON= QT_CONFIG+=alsa +ALSA_VARS= QMAKE_CONFIGURE_ARGS+=-alsa +ALSA_VARS_OFF= QMAKE_CONFIGURE_ARGS+=-no-alsa PULSEAUDIO_LIB_DEPENDS= libpulse.so:audio/pulseaudio -PULSEAUDIO_QMAKE_ON= QT_CONFIG+=pulseaudio +PULSEAUDIO_VARS= QMAKE_CONFIGURE_ARGS+=-pulseaudio +PULSEAUDIO_VARS_OFF= QMAKE_CONFIGURE_ARGS+=-no-pulseaudio +SNDIO_LIB_DEPENDS= libsndio.so:audio/sndio +SNDIO_VARS= QMAKE_CONFIGURE_ARGS+=-sndio +SNDIO_VARS_OFF= QMAKE_CONFIGURE_ARGS+=-no-sndio # We pass `norecursive' to USES=qmake because src/plugins/plugins.pro checks # whether webenginewidgets is available, which fails when qmake processes all @@ -120,6 +125,13 @@ MAKE_ENV+= CC="${CC}" CXX="${CXX}" \ post-extract: # Install FreeBSD's freebsd.pri file. ${CP} ${FILESDIR}/freebsd.pri ${WRKSRC}/src/core/config/freebsd.pri + +post-extract-SNDIO-on: + @cd ${WRKSRC}/src/3rdparty/chromium/media/audio && ${MKDIR} sndio openbsd + @${CP} ${FILESDIR}/sndio_*put.* \ + ${WRKSRC}/src/3rdparty/chromium/media/audio/sndio + @${CP} ${FILESDIR}/audio_manager_openbsd.* \ + ${WRKSRC}/src/3rdparty/chromium/media/audio/openbsd pre-configure: # Link in ${PYTHON_CMD} to ${CONFIGURE_WRKSRC}/bin -- the scripts hardcode 'python' Copied and modified: head/www/qt5-webengine/files/audio_manager_openbsd.cc (from r474875, head/www/iridium/files/audio_manager_openbsd.cc) ============================================================================== --- head/www/iridium/files/audio_manager_openbsd.cc Wed Jul 18 15:52:26 2018 (r474875, copy source) +++ head/www/qt5-webengine/files/audio_manager_openbsd.cc Sun Jul 22 04:16:38 2018 (r475084) @@ -63,12 +63,6 @@ void AudioManagerOpenBSD::GetAudioOutputDeviceNames( 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; Copied and modified: head/www/qt5-webengine/files/audio_manager_openbsd.h (from r474875, head/www/iridium/files/audio_manager_openbsd.h) ============================================================================== --- head/www/iridium/files/audio_manager_openbsd.h Wed Jul 18 15:52:26 2018 (r474875, copy source) +++ head/www/qt5-webengine/files/audio_manager_openbsd.h Sun Jul 22 04:16:38 2018 (r475084) @@ -30,7 +30,6 @@ class MEDIA_EXPORT AudioManagerOpenBSD : public AudioM void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override; AudioParameters GetInputStreamParameters( const std::string& device_id) override; - const char* GetName() override; // Implementation of AudioManagerBase. AudioOutputStream* MakeLinearOutputStream( Modified: head/www/qt5-webengine/files/freebsd.pri ============================================================================== --- head/www/qt5-webengine/files/freebsd.pri Sun Jul 22 03:22:52 2018 (r475083) +++ head/www/qt5-webengine/files/freebsd.pri Sun Jul 22 04:16:38 2018 (r475084) @@ -4,8 +4,7 @@ gn_args += disable_nacl=true \ enable_basic_printing=false \ enable_webrtc=false \ enable_hidpi=true \ - use_dbus=true \ - use_pulseaudio=false + use_dbus=true # Once the port works better, we can think about readding the diverse `use_system_<foo>` # for bundled libraries. Added: head/www/qt5-webengine/files/patch-configure.json ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/qt5-webengine/files/patch-configure.json Sun Jul 22 04:16:38 2018 (r475084) @@ -0,0 +1,33 @@ +--- configure.json.orig 2018-04-10 14:50:39 UTC ++++ configure.json +@@ -16,6 +16,7 @@ + "printing-and-pdf": "boolean", + "proprietary-codecs": "boolean", + "pulseaudio": "boolean", ++ "sndio": "boolean", + "spellchecker": "boolean", + "webrtc": "boolean" + } +@@ -113,6 +114,10 @@ + "condition": "libs.pulseaudio", + "output": [ "privateFeature" ] + }, ++ "sndio": { ++ "label": "sndio", ++ "output": [ "privateFeature" ] ++ }, + "pepper-plugins": { + "label": "Pepper Plugins", + "purpose": "Enables use of Pepper Flash and Widevine plugins.", +@@ -218,6 +223,11 @@ + { + "type": "feature", + "args": "pulseaudio", ++ "condition": "config.unix" ++ }, ++ { ++ "type": "feature", ++ "args": "sndio", + "condition": "config.unix" + }, + { Added: head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_BUILD.gn ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_BUILD.gn Sun Jul 22 04:16:38 2018 (r475084) @@ -0,0 +1,12 @@ +--- src/3rdparty/chromium/media/BUILD.gn.orig 2018-06-21 14:13:32 UTC ++++ src/3rdparty/chromium/media/BUILD.gn +@@ -53,6 +53,9 @@ config("media_config") { + if (use_cras) { + defines += [ "USE_CRAS" ] + } ++ if (use_sndio) { ++ defines += [ "USE_SNDIO" ] ++ } + } + + config("media_implementation") { Modified: head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_audio_BUILD.gn ============================================================================== --- head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_audio_BUILD.gn Sun Jul 22 03:22:52 2018 (r475083) +++ head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_audio_BUILD.gn Sun Jul 22 04:16:38 2018 (r475084) @@ -1,15 +1,15 @@ ---- src/3rdparty/chromium/media/audio/BUILD.gn.orig 2017-01-26 00:49:15 UTC +--- src/3rdparty/chromium/media/audio/BUILD.gn.orig 2018-04-10 14:05:55 UTC +++ src/3rdparty/chromium/media/audio/BUILD.gn @@ -206,7 +206,7 @@ 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" ] } -@@ -255,10 +255,12 @@ source_set("audio") { +@@ -255,10 +255,24 @@ source_set("audio") { configs += [ ":libpulse" ] } else { # TODO(ajwong): Technically, this dl should go in the action. @@ -20,6 +20,18 @@ + if (is_linux) { + libs += [ "dl" ] + } ++ } ++ ++ if (use_sndio) { ++ libs += [ "sndio" ] ++ sources += [ ++ "openbsd/audio_manager_openbsd.cc", ++ "openbsd/audio_manager_openbsd.h", ++ "sndio/sndio_input.cc", ++ "sndio/sndio_input.h", ++ "sndio/sndio_output.cc", ++ "sndio/sndio_output.h", ++ ] } configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] Added: head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_media__options.gni ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/qt5-webengine/files/patch-src_3rdparty_chromium_media_media__options.gni Sun Jul 22 04:16:38 2018 (r475084) @@ -0,0 +1,12 @@ +--- src/3rdparty/chromium/media/media_options.gni.orig 2018-06-21 14:06:20 UTC ++++ src/3rdparty/chromium/media/media_options.gni +@@ -53,6 +53,9 @@ declare_args() { + + # Enables runtime selection of ALSA library for audio. + use_alsa = false ++ ++ # Enables runtime selection of sndio library for audio. ++ 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. Added: head/www/qt5-webengine/files/patch-src_core_config_linux.pri ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/qt5-webengine/files/patch-src_core_config_linux.pri Sun Jul 22 04:16:38 2018 (r475084) @@ -0,0 +1,14 @@ +--- src/core/config/linux.pri.orig 2018-06-21 17:19:26 UTC ++++ src/core/config/linux.pri +@@ -136,6 +136,11 @@ host_build { + } else { + gn_args += use_alsa=false + } ++ qtConfig(sndio) { ++ gn_args += use_sndio=true ++ } else { ++ gn_args += use_sndio=false ++ } + packagesExist(libffi): gn_args += use_system_libffi=true + else: gn_args += use_system_libffi=false + !packagesExist(libpci): gn_args += use_libpci=false Copied: head/www/qt5-webengine/files/sndio_input.cc (from r474875, head/www/iridium/files/sndio_input.cc) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/qt5-webengine/files/sndio_input.cc Sun Jul 22 04:16:38 2018 (r475084, copy of r474875, head/www/iridium/files/sndio_input.cc) @@ -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 Copied: head/www/qt5-webengine/files/sndio_input.h (from r474875, head/www/iridium/files/sndio_input.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/qt5-webengine/files/sndio_input.h Sun Jul 22 04:16:38 2018 (r475084, copy of r474875, head/www/iridium/files/sndio_input.h) @@ -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_ Copied: head/www/qt5-webengine/files/sndio_output.cc (from r474875, head/www/iridium/files/sndio_output.cc) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/qt5-webengine/files/sndio_output.cc Sun Jul 22 04:16:38 2018 (r475084, copy of r474875, head/www/iridium/files/sndio_output.cc) @@ -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 Copied: head/www/qt5-webengine/files/sndio_output.h (from r474875, head/www/iridium/files/sndio_output.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/qt5-webengine/files/sndio_output.h Sun Jul 22 04:16:38 2018 (r475084, copy of r474875, head/www/iridium/files/sndio_output.h) @@ -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_
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201807220416.w6M4GcSr064977>