Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Jun 2017 21:49:15 +0000 (UTC)
From:      "Carlos J. Puga Medina" <cpm@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r444519 - in head/www/iridium: . files
Message-ID:  <201706272149.v5RLnFQP031722@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cpm
Date: Tue Jun 27 21:49:15 2017
New Revision: 444519
URL: https://svnweb.freebsd.org/changeset/ports/444519

Log:
  www/iridium: add SNDIO option
  
  PR:		220230
  Submitted by:	tobik

Added:
  head/www/iridium/files/audio_manager_openbsd.cc   (contents, props changed)
  head/www/iridium/files/audio_manager_openbsd.h   (contents, props changed)
  head/www/iridium/files/patch-media_BUILD.gn   (contents, props changed)
  head/www/iridium/files/patch-media_media_options.gni   (contents, props changed)
  head/www/iridium/files/sndio_input.cc   (contents, props changed)
  head/www/iridium/files/sndio_input.h   (contents, props changed)
  head/www/iridium/files/sndio_output.cc   (contents, props changed)
  head/www/iridium/files/sndio_output.h   (contents, props changed)
Modified:
  head/www/iridium/Makefile
  head/www/iridium/files/patch-media_audio_BUILD.gn

Modified: head/www/iridium/Makefile
==============================================================================
--- head/www/iridium/Makefile	Tue Jun 27 19:36:37 2017	(r444518)
+++ head/www/iridium/Makefile	Tue Jun 27 21:49:15 2017	(r444519)
@@ -104,7 +104,7 @@ SUB_LIST+=	COMMENT="${COMMENT}"
 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_LIB_DEPENDS=	libasound.so:audio/alsa-lib
 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>
 
@@ -191,6 +199,12 @@ pre-everything::
 	@${ECHO_MSG} "and a fair amount of free diskspace (~ 3.7GB)."
 .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

Added: head/www/iridium/files/audio_manager_openbsd.cc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/iridium/files/audio_manager_openbsd.cc	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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

Added: head/www/iridium/files/audio_manager_openbsd.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/iridium/files/audio_manager_openbsd.h	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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_

Added: head/www/iridium/files/patch-media_BUILD.gn
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/iridium/files/patch-media_BUILD.gn	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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" ]
+   }

Modified: head/www/iridium/files/patch-media_audio_BUILD.gn
==============================================================================
--- head/www/iridium/files/patch-media_audio_BUILD.gn	Tue Jun 27 19:36:37 2017	(r444518)
+++ head/www/iridium/files/patch-media_audio_BUILD.gn	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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 {

Added: head/www/iridium/files/patch-media_media_options.gni
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/iridium/files/patch-media_media_options.gni	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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 &&

Added: head/www/iridium/files/sndio_input.cc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/iridium/files/sndio_input.cc	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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

Added: head/www/iridium/files/sndio_input.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/iridium/files/sndio_input.h	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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_

Added: head/www/iridium/files/sndio_output.cc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/iridium/files/sndio_output.cc	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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

Added: head/www/iridium/files/sndio_output.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/www/iridium/files/sndio_output.h	Tue Jun 27 21:49:15 2017	(r444519)
@@ -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?201706272149.v5RLnFQP031722>