View | Details | Raw Unified | Return to bug 220230 | Differences between
and this patch

Collapse All | Expand All

(-)Makefile (-1 / +15 lines)
Lines 104-110 Link Here
104
OPTIONS_DEFINE=	CODECS DEBUG GCONF KERBEROS
104
OPTIONS_DEFINE=	CODECS DEBUG GCONF KERBEROS
105
CODECS_DESC=	Compile and enable patented codecs like H.264
105
CODECS_DESC=	Compile and enable patented codecs like H.264
106
OPTIONS_GROUP=		AUDIO
106
OPTIONS_GROUP=		AUDIO
107
OPTIONS_GROUP_AUDIO=	ALSA PULSEAUDIO
107
OPTIONS_GROUP_AUDIO=	ALSA PULSEAUDIO SNDIO
108
108
109
OPTIONS_DEFAULT=	ALSA CODECS GCONF KERBEROS
109
OPTIONS_DEFAULT=	ALSA CODECS GCONF KERBEROS
110
OPTIONS_SUB=		yes
110
OPTIONS_SUB=		yes
Lines 114-119 Link Here
114
ALSA_RUN_DEPENDS=	${LOCALBASE}/lib/alsa-lib/libasound_module_pcm_oss.so:audio/alsa-plugins \
114
ALSA_RUN_DEPENDS=	${LOCALBASE}/lib/alsa-lib/libasound_module_pcm_oss.so:audio/alsa-plugins \
115
			alsa-lib>=1.1.1_1:audio/alsa-lib
115
			alsa-lib>=1.1.1_1:audio/alsa-lib
116
PULSEAUDIO_LIB_DEPENDS=	libpulse.so:audio/pulseaudio
116
PULSEAUDIO_LIB_DEPENDS=	libpulse.so:audio/pulseaudio
117
# With SNDIO=on we exclude audio_manager_linux from the build (see
118
# media/audio/BUILD.gn) and use audio_manager_openbsd which does not
119
# support falling back to ALSA.  In theory it supports falling back to
120
# PulseAudio, but this is untested.
121
SNDIO_PREVENTS=		ALSA PULSEAUDIO
122
SNDIO_LIB_DEPENDS=	libsndio.so:audio/sndio
123
SNDIO_VARS=		GN_ARGS+=use_sndio=true
124
SNDIO_VARS_OFF=		GN_ARGS+=use_sndio=false
117
125
118
.include <bsd.port.options.mk>
126
.include <bsd.port.options.mk>
119
127
Lines 192-197 Link Here
192
.endif
200
.endif
193
	@${ECHO_MSG}
201
	@${ECHO_MSG}
194
202
203
post-patch-SNDIO-on:
204
	@${MKDIR} ${WRKSRC}/media/audio/sndio ${WRKSRC}/media/audio/openbsd
205
	@${CP} ${FILESDIR}/sndio_output.* ${WRKSRC}/media/audio/sndio
206
	@${CP} ${FILESDIR}/sndio_input.* ${WRKSRC}/media/audio/sndio
207
	@${CP} ${FILESDIR}/audio_manager_openbsd.* ${WRKSRC}/media/audio/openbsd
208
195
pre-configure:
209
pre-configure:
196
	# We used to remove bundled libraries to be sure that iridium uses
210
	# We used to remove bundled libraries to be sure that iridium uses
197
	# system libraries and not shippen ones.
211
	# system libraries and not shippen ones.
(-)files/audio_manager_openbsd.cc (+205 lines)
Line 0 Link Here
1
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#include "base/metrics/histogram_macros.h"
6
7
#include "media/audio/openbsd/audio_manager_openbsd.h"
8
9
#include "media/audio/audio_device_description.h"
10
#include "media/audio/audio_output_dispatcher.h"
11
#if defined(USE_PULSEAUDIO)
12
#include "media/audio/pulse/audio_manager_pulse.h"
13
#endif
14
#if defined(USE_SNDIO)
15
#include "media/audio/sndio/sndio_input.h"
16
#include "media/audio/sndio/sndio_output.h"
17
#else
18
#include "media/audio/fake_audio_manager.h"
19
#endif
20
#include "media/base/limits.h"
21
#include "media/base/media_switches.h"
22
23
namespace media {
24
25
enum OpenBSDAudioIO {
26
  kPulse,
27
  kSndio,
28
  kAudioIOMax = kSndio
29
};
30
31
#if defined(USE_SNDIO)
32
// Maximum number of output streams that can be open simultaneously.
33
static const int kMaxOutputStreams = 4;
34
35
// Default sample rate for input and output streams.
36
static const int kDefaultSampleRate = 48000;
37
38
void AddDefaultDevice(AudioDeviceNames* device_names) {
39
  DCHECK(device_names->empty());
40
  device_names->push_front(AudioDeviceName::CreateDefault());
41
}
42
43
bool AudioManagerOpenBSD::HasAudioOutputDevices() {
44
  return true;
45
}
46
47
bool AudioManagerOpenBSD::HasAudioInputDevices() {
48
  return true;
49
}
50
51
void AudioManagerOpenBSD::ShowAudioInputSettings() {
52
  NOTIMPLEMENTED();
53
}
54
55
void AudioManagerOpenBSD::GetAudioInputDeviceNames(
56
    AudioDeviceNames* device_names) {
57
  DCHECK(device_names->empty());
58
  AddDefaultDevice(device_names);
59
}
60
61
void AudioManagerOpenBSD::GetAudioOutputDeviceNames(
62
    AudioDeviceNames* device_names) {
63
  AddDefaultDevice(device_names);
64
}
65
66
#if defined(USE_SNDIO)
67
const char* AudioManagerOpenBSD::GetName() {
68
  return "SNDIO";
69
}
70
#endif
71
72
AudioParameters AudioManagerOpenBSD::GetInputStreamParameters(
73
    const std::string& device_id) {
74
  static const int kDefaultInputBufferSize = 1024;
75
76
  int user_buffer_size = GetUserBufferSize();
77
  int buffer_size = user_buffer_size ?
78
      user_buffer_size : kDefaultInputBufferSize;
79
80
  return AudioParameters(
81
      AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
82
      kDefaultSampleRate, 16, buffer_size);
83
}
84
85
AudioManagerOpenBSD::AudioManagerOpenBSD(
86
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
87
    scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
88
    AudioLogFactory* audio_log_factory)
89
    : AudioManagerBase(std::move(task_runner),
90
                       std::move(worker_task_runner),
91
                       audio_log_factory) {
92
  DLOG(WARNING) << "AudioManagerOpenBSD";
93
  SetMaxOutputStreamsAllowed(kMaxOutputStreams);
94
}
95
96
AudioManagerOpenBSD::~AudioManagerOpenBSD() {
97
  Shutdown();
98
}
99
100
AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
101
    const AudioParameters& params,
102
    const LogCallback& log_callback) {
103
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
104
  return MakeOutputStream(params);
105
}
106
107
AudioOutputStream* AudioManagerOpenBSD::MakeLowLatencyOutputStream(
108
    const AudioParameters& params,
109
    const std::string& device_id,
110
    const LogCallback& log_callback) {
111
  DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!";
112
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
113
  return MakeOutputStream(params);
114
}
115
116
AudioInputStream* AudioManagerOpenBSD::MakeLinearInputStream(
117
    const AudioParameters& params,
118
    const std::string& device_id,
119
    const LogCallback& log_callback) {
120
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
121
  return MakeInputStream(params);
122
}
123
124
AudioInputStream* AudioManagerOpenBSD::MakeLowLatencyInputStream(
125
    const AudioParameters& params,
126
    const std::string& device_id,
127
    const LogCallback& log_callback) {
128
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
129
  return MakeInputStream(params);
130
}
131
132
AudioParameters AudioManagerOpenBSD::GetPreferredOutputStreamParameters(
133
    const std::string& output_device_id,
134
    const AudioParameters& input_params) {
135
  // TODO(tommi): Support |output_device_id|.
136
  DLOG_IF(ERROR, !output_device_id.empty()) << "Not implemented!";
137
  static const int kDefaultOutputBufferSize = 2048;
138
139
  ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
140
  int sample_rate = kDefaultSampleRate;
141
  int buffer_size = kDefaultOutputBufferSize;
142
  int bits_per_sample = 16;
143
  if (input_params.IsValid()) {
144
    sample_rate = input_params.sample_rate();
145
    bits_per_sample = input_params.bits_per_sample();
146
    channel_layout = input_params.channel_layout();
147
    buffer_size = std::min(buffer_size, input_params.frames_per_buffer());
148
  }
149
150
  int user_buffer_size = GetUserBufferSize();
151
  if (user_buffer_size)
152
    buffer_size = user_buffer_size;
153
154
  return AudioParameters(
155
      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
156
      sample_rate, bits_per_sample, buffer_size);
157
}
158
159
AudioInputStream* AudioManagerOpenBSD::MakeInputStream(
160
    const AudioParameters& params) {
161
  DLOG(WARNING) << "MakeInputStream";
162
  return new SndioAudioInputStream(this,
163
             AudioDeviceDescription::kDefaultDeviceId, params);
164
}
165
166
AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream(
167
    const AudioParameters& params) {
168
  DLOG(WARNING) << "MakeOutputStream";
169
  return new SndioAudioOutputStream(params, this);
170
}
171
#endif
172
173
ScopedAudioManagerPtr CreateAudioManager(
174
    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
175
    scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
176
    AudioLogFactory* audio_log_factory) {
177
  DLOG(WARNING) << "CreateAudioManager";
178
#if defined(USE_PULSEAUDIO)
179
  // Do not move task runners when creating AudioManagerPulse.
180
  // If the creation fails, we need to use the task runners to create other
181
  // AudioManager implementations.
182
  std::unique_ptr<AudioManagerPulse, AudioManagerDeleter> manager(
183
      new AudioManagerPulse(task_runner, worker_task_runner,
184
                            audio_log_factory));
185
  if (manager->Init()) {
186
    UMA_HISTOGRAM_ENUMERATION("Media.OpenBSDAudioIO", kPulse, kAudioIOMax + 1);
187
    return std::move(manager);
188
  }
189
  DVLOG(1) << "PulseAudio is not available on the OS";
190
#endif
191
192
#if defined(USE_SNDIO)
193
  UMA_HISTOGRAM_ENUMERATION("Media.OpenBSDAudioIO", kSndio, kAudioIOMax + 1);
194
  return ScopedAudioManagerPtr(
195
      new AudioManagerOpenBSD(std::move(task_runner),
196
                              std::move(worker_task_runner),audio_log_factory));
197
#else
198
  return ScopedAudioManagerPtr(
199
      new FakeAudioManager(std::move(task_runner),
200
                           std::move(worker_task_runner), audio_log_factory));
201
#endif
202
203
}
204
205
}  // namespace media
(-)files/audio_manager_openbsd.h (+69 lines)
Line 0 Link Here
1
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#ifndef MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
6
#define MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
7
8
#include <set>
9
10
#include "base/compiler_specific.h"
11
#include "base/macros.h"
12
#include "base/memory/ref_counted.h"
13
#include "base/threading/thread.h"
14
#include "media/audio/audio_manager_base.h"
15
16
namespace media {
17
18
class MEDIA_EXPORT AudioManagerOpenBSD : public AudioManagerBase {
19
 public:
20
  AudioManagerOpenBSD(
21
      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
22
      scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner,
23
      AudioLogFactory* audio_log_factory);
24
25
  // Implementation of AudioManager.
26
  bool HasAudioOutputDevices() override;
27
  bool HasAudioInputDevices() override;
28
  void ShowAudioInputSettings() override;
29
  void GetAudioInputDeviceNames(AudioDeviceNames* device_names) override;
30
  void GetAudioOutputDeviceNames(AudioDeviceNames* device_names) override;
31
  AudioParameters GetInputStreamParameters(
32
      const std::string& device_id) override;
33
  const char* GetName() override;
34
35
  // Implementation of AudioManagerBase.
36
  AudioOutputStream* MakeLinearOutputStream(
37
      const AudioParameters& params,
38
      const LogCallback& log_callback) override;
39
  AudioOutputStream* MakeLowLatencyOutputStream(
40
      const AudioParameters& params,
41
      const std::string& device_id,
42
      const LogCallback& log_callback) override;
43
  AudioInputStream* MakeLinearInputStream(
44
      const AudioParameters& params,
45
      const std::string& device_id,
46
      const LogCallback& log_callback) override;
47
  AudioInputStream* MakeLowLatencyInputStream(
48
      const AudioParameters& params,
49
      const std::string& device_id,
50
      const LogCallback& log_callback) override;
51
52
 protected:
53
  ~AudioManagerOpenBSD() override;
54
55
  AudioParameters GetPreferredOutputStreamParameters(
56
      const std::string& output_device_id,
57
      const AudioParameters& input_params) override;
58
59
 private:
60
  // Called by MakeLinearOutputStream and MakeLowLatencyOutputStream.
61
  AudioOutputStream* MakeOutputStream(const AudioParameters& params);
62
  AudioInputStream* MakeInputStream(const AudioParameters& params);
63
64
  DISALLOW_COPY_AND_ASSIGN(AudioManagerOpenBSD);
65
};
66
67
}  // namespace media
68
69
#endif  // MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
(-)files/patch-media_BUILD.gn (+13 lines)
Line 0 Link Here
1
$OpenBSD: patch-media_BUILD_gn,v 1.2 2017/04/28 22:22:36 robert Exp $
2
--- media/BUILD.gn.orig.port	Wed Apr 19 21:06:35 2017
3
+++ media/BUILD.gn	Thu Apr 27 19:56:02 2017
4
@@ -56,6 +56,9 @@ config("media_config") {
5
       defines += [ "DLOPEN_PULSEAUDIO" ]
6
     }
7
   }
8
+  if (use_sndio) {
9
+    defines += [ "USE_SNDIO" ]
10
+  }
11
   if (use_cras) {
12
     defines += [ "USE_CRAS" ]
13
   }
(-)files/patch-media_audio_BUILD.gn (-2 / +14 lines)
Lines 1-14 Link Here
1
--- media/audio/BUILD.gn.orig	2017-04-19 19:06:35 UTC
1
--- media/audio/BUILD.gn.orig	2017-04-19 19:06:35 UTC
2
+++ media/audio/BUILD.gn
2
+++ media/audio/BUILD.gn
3
@@ -212,7 +212,7 @@ source_set("audio") {
3
@@ -212,9 +212,19 @@ source_set("audio") {
4
     deps += [ "//media/base/android:media_jni_headers" ]
4
     deps += [ "//media/base/android:media_jni_headers" ]
5
   }
5
   }
6
 
6
 
7
-  if (is_linux) {
7
-  if (is_linux) {
8
+  if (is_linux || is_bsd) {
8
+  if (is_linux || (is_bsd && !use_sndio)) {
9
     sources += [ "linux/audio_manager_linux.cc" ]
9
     sources += [ "linux/audio_manager_linux.cc" ]
10
   }
10
   }
11
+  if (use_sndio) {
12
+    libs += [ "sndio" ]
13
+    sources += [
14
+      "openbsd/audio_manager_openbsd.cc",
15
+      "sndio/sndio_input.cc",
16
+      "sndio/sndio_input.h",
17
+      "sndio/sndio_output.cc",
18
+      "sndio/sndio_output.h"
19
+    ]
20
+  }
11
 
21
 
22
   if (use_alsa) {
23
     libs += [ "asound" ]
12
@@ -261,10 +261,12 @@ source_set("audio") {
24
@@ -261,10 +261,12 @@ source_set("audio") {
13
       configs += [ ":libpulse" ]
25
       configs += [ ":libpulse" ]
14
     } else {
26
     } else {
(-)files/patch-media_media_options.gni (+13 lines)
Line 0 Link Here
1
$OpenBSD: patch-media_media_options_gni,v 1.3 2017/04/28 22:22:36 robert Exp $
2
--- media/media_options.gni.orig	2017-04-19 21:06:35.000000000 +0200
3
+++ media/media_options.gni	2017-05-06 22:11:03.288488000 +0200
4
@@ -73,6 +73,9 @@
5
   # Enables runtime selection of ALSA library for audio.
6
   use_alsa = false
7
 
8
+  # Enable runtime selection of sndio(7)
9
+  use_sndio = false
10
+
11
   # Alsa should be used on non-Android, non-Mac POSIX systems.
12
   # Alsa should be used on desktop Chromecast and audio-only Chromecast builds.
13
   if (is_posix && !is_android && !is_mac &&
(-)files/sndio_input.cc (+190 lines)
Line 0 Link Here
1
// Copyright 2013 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#include "media/audio/sndio/sndio_input.h"
6
7
#include <stddef.h>
8
9
#include "base/bind.h"
10
#include "base/logging.h"
11
#include "base/macros.h"
12
#include "base/message_loop/message_loop.h"
13
#include "media/audio/openbsd/audio_manager_openbsd.h"
14
#include "media/audio/audio_manager.h"
15
16
namespace media {
17
18
void sndio_in_onmove(void *arg, int delta) {
19
  NOTIMPLEMENTED();
20
  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
21
22
  self->hw_delay_ = delta - self->params_.GetBytesPerFrame();
23
}
24
25
void *sndio_in_threadstart(void *arg) {
26
  NOTIMPLEMENTED();
27
  SndioAudioInputStream* self = static_cast<SndioAudioInputStream*>(arg);
28
29
  self->ReadAudio();
30
  return NULL;
31
}
32
33
SndioAudioInputStream::SndioAudioInputStream(AudioManagerBase* audio_manager,
34
                                       const std::string& device_name,
35
                                       const AudioParameters& params)
36
    : audio_manager_(audio_manager),
37
      device_name_(device_name),
38
      params_(params),
39
      bytes_per_buffer_(params.frames_per_buffer() *
40
                        (params.channels() * params.bits_per_sample()) /
41
                        8),
42
      buffer_duration_(base::TimeDelta::FromMicroseconds(
43
          params.frames_per_buffer() * base::Time::kMicrosecondsPerSecond /
44
          static_cast<float>(params.sample_rate()))),
45
      callback_(NULL),
46
      device_handle_(NULL),
47
      read_callback_behind_schedule_(false),
48
      audio_bus_(AudioBus::Create(params)) {
49
}
50
51
SndioAudioInputStream::~SndioAudioInputStream() {}
52
53
bool SndioAudioInputStream::Open() {
54
  struct sio_par par;
55
  int sig;
56
57
  if (device_handle_)
58
    return false;  // Already open.
59
60
  if (params_.format() != AudioParameters::AUDIO_PCM_LINEAR &&
61
      params_.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
62
    LOG(WARNING) << "Unsupported audio format.";
63
    return false;
64
  }
65
66
  sio_initpar(&par);
67
  par.rate = params_.sample_rate();
68
  par.pchan = params_.channels();
69
  par.bits = params_.bits_per_sample();
70
  par.bps = par.bits / 8;
71
  par.sig = sig = par.bits != 8 ? 1 : 0;
72
  par.le = SIO_LE_NATIVE;
73
  par.appbufsz = params_.frames_per_buffer();
74
  sndio_rec_bufsz_ = par.bufsz;
75
  sndio_rec_bufsize_ = par.round * par.bps * par.rchan;
76
77
  device_handle_ = sio_open(SIO_DEVANY, SIO_REC, 0);
78
79
  if (device_handle_ == NULL) {
80
    LOG(ERROR) << "Couldn't open audio device.";
81
    return false;
82
  }
83
84
  if (!sio_setpar(device_handle_, &par) || !sio_getpar(device_handle_, &par)) {
85
    LOG(ERROR) << "Couldn't set audio parameters.";
86
    goto bad_close;
87
  }
88
89
  if (par.rate  != (unsigned int)params_.sample_rate() ||
90
      par.pchan != (unsigned int)params_.channels() ||
91
      par.bits  != (unsigned int)params_.bits_per_sample() ||
92
      par.sig   != (unsigned int)sig ||
93
      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
94
      (par.bits != par.bps * 8)) {
95
    LOG(ERROR) << "Unsupported audio parameters.";
96
    goto bad_close;
97
  }
98
  sio_onmove(device_handle_, sndio_in_onmove, this);
99
100
  audio_buffer_.reset(new uint8_t[bytes_per_buffer_]);
101
102
  return true;
103
bad_close:
104
  sio_close(device_handle_);
105
  return false;
106
}
107
108
void SndioAudioInputStream::Start(AudioInputCallback* callback) {
109
  DCHECK(!callback_ && callback);
110
  callback_ = callback;
111
  StartAgc();
112
113
  // We start reading data half |buffer_duration_| later than when the
114
  // buffer might have got filled, to accommodate some delays in the audio
115
  // driver. This could also give us a smooth read sequence going forward.
116
  base::TimeDelta delay = buffer_duration_ + buffer_duration_ / 2;
117
  next_read_time_ = base::TimeTicks::Now() + delay;
118
  if (pthread_create(&thread_, NULL, sndio_in_threadstart, this) != 0)
119
    LOG(ERROR) << "Failed to create real-time thread.";
120
}
121
122
void SndioAudioInputStream::ReadAudio() {
123
  NOTIMPLEMENTED();
124
  DCHECK(callback_);
125
126
  int num_buffers = sndio_rec_bufsize_ / params_.frames_per_buffer();
127
  double normalized_volume = 0.0;
128
129
  // Update the AGC volume level once every second. Note that, |volume| is
130
  // also updated each time SetVolume() is called through IPC by the
131
  // render-side AGC.
132
  GetAgcVolume(&normalized_volume);
133
134
  while (num_buffers--) {
135
    int frames_read = sio_read(device_handle_, audio_buffer_.get(),
136
                                         params_.frames_per_buffer());
137
    if (frames_read == params_.frames_per_buffer()) {
138
      audio_bus_->FromInterleaved(audio_buffer_.get(),
139
                                  audio_bus_->frames(),
140
                                  params_.bits_per_sample() / 8);
141
      callback_->OnData(
142
          this, audio_bus_.get(), hw_delay_, normalized_volume);
143
    } else {
144
      LOG(WARNING) << "sio_read() returning less than expected frames: "
145
                   << frames_read << " vs. " << params_.frames_per_buffer()
146
                   << ". Dropping this buffer.";
147
    }
148
  }
149
}
150
151
void SndioAudioInputStream::Stop() {
152
  if (!device_handle_ || !callback_)
153
    return;
154
155
  StopAgc();
156
157
  pthread_join(thread_, NULL);
158
  sio_stop(device_handle_);
159
160
  callback_ = NULL;
161
}
162
163
void SndioAudioInputStream::Close() {
164
  if (device_handle_) {
165
    sio_close(device_handle_);
166
    audio_buffer_.reset();
167
    device_handle_ = NULL;
168
  }
169
170
  audio_manager_->ReleaseInputStream(this);
171
}
172
173
double SndioAudioInputStream::GetMaxVolume() {
174
  return static_cast<double>(SIO_MAXVOL);
175
}
176
177
void SndioAudioInputStream::SetVolume(double volume) {
178
  NOTIMPLEMENTED();
179
}
180
181
double SndioAudioInputStream::GetVolume() {
182
  long current_volume = 0;
183
  return static_cast<double>(current_volume);
184
}
185
186
bool SndioAudioInputStream::IsMuted() {
187
  return false;
188
}
189
190
}  // namespace media
(-)files/sndio_input.h (+108 lines)
Line 0 Link Here
1
// Copyright 2013 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#ifndef MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
6
#define MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
7
8
#include <stdint.h>
9
#include <string>
10
#include <sndio.h>
11
12
#include "base/compiler_specific.h"
13
#include "base/macros.h"
14
#include "base/memory/weak_ptr.h"
15
#include "base/time/time.h"
16
#include "media/audio/agc_audio_stream.h"
17
#include "media/audio/audio_io.h"
18
#include "media/audio/audio_device_description.h"
19
#include "media/base/audio_parameters.h"
20
21
namespace media {
22
23
class AudioManagerBase;
24
25
// call-backs invoked from C libraries, thus requiring C linkage
26
extern "C" {
27
  // Invoked (on the real-time thread) at each sound card clock tick
28
  void sndio_in_onmove(void *arg, int delta);
29
  // Invoked (on the real-time thread) whenever the volume changes
30
  void sndio_in_onvol(void *arg, unsigned int vol);
31
  // Real-time thread entry point
32
  void *sndio_in_threadstart(void *arg);
33
}
34
35
// Provides an input stream for audio capture based on the SNDIO PCM interface.
36
// This object is not thread safe and all methods should be invoked in the
37
// thread that created the object.
38
class SndioAudioInputStream : public AgcAudioStream<AudioInputStream> {
39
 public:
40
  // Pass this to the constructor if you want to attempt auto-selection
41
  // of the audio recording device.
42
  static const char kAutoSelectDevice[];
43
44
  // Create a PCM Output stream for the SNDIO device identified by
45
  // |device_name|. If unsure of what to use for |device_name|, use
46
  // |kAutoSelectDevice|.
47
  SndioAudioInputStream(AudioManagerBase* audio_manager,
48
                     const std::string& device_name,
49
                     const AudioParameters& params);
50
51
  ~SndioAudioInputStream() override;
52
53
  // Implementation of AudioInputStream.
54
  bool Open() override;
55
  void Start(AudioInputCallback* callback) override;
56
  void Stop() override;
57
  void Close() override;
58
  double GetMaxVolume() override;
59
  void SetVolume(double volume) override;
60
  double GetVolume() override;
61
  bool IsMuted() override;
62
63
  // C-linkage call-backs are friends to access private data
64
  friend void sndio_in_onmove(void *arg, int delta);
65
  friend void sndio_in_onvol(void *arg, unsigned int vol);
66
  friend void *sndio_in_threadstart(void *arg);
67
68
 private:
69
  // Logs the error and invokes any registered callbacks.
70
  void HandleError(const char* method, int error);
71
72
  // Reads one or more buffers of audio from the device, passes on to the
73
  // registered callback and schedules the next read.
74
  void ReadAudio();
75
76
  // Recovers from any device errors if possible.
77
  bool Recover(int error);
78
79
  // Non-refcounted pointer back to the audio manager.
80
  // The AudioManager indirectly holds on to stream objects, so we don't
81
  // want circular references.  Additionally, stream objects live on the audio
82
  // thread, which is owned by the audio manager and we don't want to addref
83
  // the manager from that thread.
84
  AudioManagerBase* audio_manager_;
85
  std::string device_name_;
86
  AudioParameters params_;
87
  int bytes_per_buffer_;
88
  base::TimeDelta buffer_duration_;  // Length of each recorded buffer.
89
  AudioInputCallback* callback_;  // Valid during a recording session.
90
  base::TimeTicks next_read_time_;  // Scheduled time for next read callback.
91
  struct sio_hdl* device_handle_;  // Handle to the SNDIO PCM recording device.
92
  std::unique_ptr<uint8_t[]> audio_buffer_;  // Buffer used for reading audio data.
93
  bool read_callback_behind_schedule_;
94
  std::unique_ptr<AudioBus> audio_bus_;
95
96
  int hw_delay_;
97
  int sndio_rec_bufsize_;
98
  int sndio_rec_bufsz_;
99
100
  // High priority thread running RealTimeThread()
101
  pthread_t thread_;
102
103
  DISALLOW_COPY_AND_ASSIGN(SndioAudioInputStream);
104
};
105
106
}  // namespace media
107
108
#endif  // MEDIA_AUDIO_SNDIO_SNDIO_INPUT_H_
(-)files/sndio_output.cc (+177 lines)
Line 0 Link Here
1
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#include "base/logging.h"
6
#include "base/time/time.h"
7
#include "base/time/default_tick_clock.h"
8
#include "media/audio/audio_manager_base.h"
9
#include "media/base/audio_timestamp_helper.h"
10
#include "media/audio/sndio/sndio_output.h"
11
12
namespace media {
13
14
void sndio_onmove(void *arg, int delta) {
15
  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
16
17
  self->hw_delay = delta;
18
}
19
20
void sndio_onvol(void *arg, unsigned int vol) {
21
  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
22
23
  self->vol = vol;
24
}
25
26
void *sndio_threadstart(void *arg) {
27
  SndioAudioOutputStream* self = static_cast<SndioAudioOutputStream*>(arg);
28
29
  self->RealTimeThread();
30
  return NULL;
31
}
32
33
SndioAudioOutputStream::SndioAudioOutputStream(const AudioParameters& params,
34
                                               AudioManagerBase* manager)
35
    : manager(manager),
36
      params(params),
37
      audio_bus(AudioBus::Create(params)),
38
      bytes_per_frame(params.GetBytesPerFrame()),
39
      state(kClosed),
40
      mutex(PTHREAD_MUTEX_INITIALIZER) {
41
}
42
43
SndioAudioOutputStream::~SndioAudioOutputStream() {
44
  if (state != kClosed)
45
    Close();
46
}
47
48
bool SndioAudioOutputStream::Open() {
49
  struct sio_par par;
50
  int sig;
51
52
  if (params.format() != AudioParameters::AUDIO_PCM_LINEAR &&
53
      params.format() != AudioParameters::AUDIO_PCM_LOW_LATENCY) {
54
    LOG(WARNING) << "Unsupported audio format.";
55
    return false;
56
  }
57
  sio_initpar(&par);
58
  par.rate = params.sample_rate();
59
  par.pchan = params.channels();
60
  par.bits = params.bits_per_sample();
61
  par.bps = par.bits / 8;
62
  par.sig = sig = par.bits != 8 ? 1 : 0;
63
  par.le = SIO_LE_NATIVE;
64
  par.appbufsz = params.frames_per_buffer();
65
66
  hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
67
  if (hdl == NULL) {
68
    LOG(ERROR) << "Couldn't open audio device.";
69
    return false;
70
  }
71
  if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
72
    LOG(ERROR) << "Couldn't set audio parameters.";
73
    goto bad_close;
74
  }
75
  if (par.rate  != (unsigned int)params.sample_rate() ||
76
      par.pchan != (unsigned int)params.channels() ||
77
      par.bits  != (unsigned int)params.bits_per_sample() ||
78
      par.sig   != (unsigned int)sig ||
79
      (par.bps > 1 && par.le != SIO_LE_NATIVE) ||
80
      (par.bits != par.bps * 8)) {
81
    LOG(ERROR) << "Unsupported audio parameters.";
82
    goto bad_close;
83
  }
84
  state = kStopped;
85
  volpending = 0;
86
  vol = 0;
87
  buffer = new char[audio_bus->frames() * params.GetBytesPerFrame()];
88
  sio_onmove(hdl, sndio_onmove, this);
89
  sio_onvol(hdl, sndio_onvol, this);
90
  return true;
91
 bad_close:
92
  sio_close(hdl);
93
  return false;
94
}
95
96
void SndioAudioOutputStream::Close() {
97
  if (state == kClosed)
98
    return;
99
  if (state == kRunning)
100
    Stop();
101
  state = kClosed;
102
  delete [] buffer;
103
  sio_close(hdl);
104
  manager->ReleaseOutputStream(this);  // Calls the destructor
105
}
106
107
void SndioAudioOutputStream::Start(AudioSourceCallback* callback) {
108
  state = kRunning;
109
  hw_delay = 0;
110
  source = callback;
111
  sio_start(hdl);
112
  if (pthread_create(&thread, NULL, sndio_threadstart, this) != 0) {
113
    LOG(ERROR) << "Failed to create real-time thread.";
114
    sio_stop(hdl);
115
    state = kStopped;
116
  }
117
}
118
119
void SndioAudioOutputStream::Stop() {
120
  if (state == kStopped)
121
    return;
122
  state = kStopWait;
123
  pthread_join(thread, NULL);
124
  sio_stop(hdl);
125
  state = kStopped;
126
}
127
128
void SndioAudioOutputStream::SetVolume(double v) {
129
  pthread_mutex_lock(&mutex);
130
  vol = v * SIO_MAXVOL;
131
  volpending = 1;
132
  pthread_mutex_unlock(&mutex);
133
}
134
135
void SndioAudioOutputStream::GetVolume(double* v) {
136
  pthread_mutex_lock(&mutex);
137
  *v = vol * (1. / SIO_MAXVOL);
138
  pthread_mutex_unlock(&mutex);
139
}
140
141
void SndioAudioOutputStream::RealTimeThread(void) {
142
  int avail, count;
143
144
  while (state == kRunning) {
145
    // Update volume if needed
146
    pthread_mutex_lock(&mutex);
147
    if (volpending) {
148
      volpending = 0;
149
      sio_setvol(hdl, vol);
150
    }
151
    pthread_mutex_unlock(&mutex);
152
153
    // Get data to play
154
    const base::TimeDelta delay = AudioTimestampHelper::FramesToTime(hw_delay, params.sample_rate() * 1000);
155
    count = source->OnMoreData(delay, base::TimeTicks::Now(), 0, audio_bus.get());
156
    audio_bus->ToInterleaved(count, params.bits_per_sample() / 8, buffer);
157
    if (count == 0) {
158
      // We have to submit something to the device
159
      count = audio_bus->frames();
160
      memset(buffer, 0, count * params.GetBytesPerFrame());
161
      LOG(WARNING) << "No data to play, running empty cycle.";
162
    }
163
164
    // Submit data to the device
165
    avail = count * params.GetBytesPerFrame();
166
    count = sio_write(hdl, buffer, avail);
167
    if (count == 0) {
168
      LOG(WARNING) << "Audio device disconnected.";
169
      break;
170
    }
171
172
    // Update hardware pointer
173
    hw_delay += count;
174
  }
175
}
176
177
}  // namespace media
(-)files/sndio_output.h (+92 lines)
Line 0 Link Here
1
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#ifndef MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
6
#define MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_
7
8
#include <pthread.h>
9
#include <sndio.h>
10
11
#include "base/time/tick_clock.h"
12
#include "base/time/time.h"
13
#include "media/audio/audio_io.h"
14
15
16
namespace media {
17
18
class AudioParameters;
19
class AudioManagerBase;
20
21
// call-backs invoked from C libraries, thus requiring C linkage
22
extern "C" {
23
  // Invoked (on the real-time thread) at each sound card clock tick
24
  void sndio_onmove(void *arg, int delta);
25
  // Invoked (on the real-time thread) whenever the volume changes
26
  void sndio_onvol(void *arg, unsigned int vol);
27
  // Real-time thread entry point
28
  void *sndio_threadstart(void *arg);
29
}
30
31
// Implementation of AudioOutputStream using sndio(7)
32
class SndioAudioOutputStream : public AudioOutputStream {
33
 public:
34
  // The manager is creating this object
35
  SndioAudioOutputStream(const AudioParameters& params,
36
                         AudioManagerBase* manager);
37
  virtual ~SndioAudioOutputStream();
38
39
  // Implementation of AudioOutputStream.
40
  virtual bool Open() override;
41
  virtual void Close() override;
42
  virtual void Start(AudioSourceCallback* callback) override;
43
  virtual void Stop() override;
44
  virtual void SetVolume(double volume) override;
45
  virtual void GetVolume(double* volume) override;
46
47
  // C-linkage call-backs are friends to access private data
48
  friend void sndio_onmove(void *arg, int delta);
49
  friend void sndio_onvol(void *arg, unsigned int vol);
50
  friend void *sndio_threadstart(void *arg);
51
52
 private:
53
  enum StreamState {
54
    kClosed,            // Not opened yet
55
    kStopped,           // Device opened, but not started yet
56
    kRunning,           // Started, device playing
57
    kStopWait           // Stopping, waiting for the real-time thread to exit
58
  };
59
  // Continuously moves data from the audio bus to the device
60
  void RealTimeThread(void);
61
  // Our creator, the audio manager needs to be notified when we close.
62
  AudioManagerBase* manager;
63
  // Parameters of the source
64
  AudioParameters params;
65
  // Source stores data here
66
  std::unique_ptr<AudioBus> audio_bus;
67
  int bytes_per_frame;
68
  // Call-back that produces data to play
69
  AudioSourceCallback* source;
70
  // Handle of the audio device
71
  struct sio_hdl* hdl;
72
  // Current state of the stream
73
  enum StreamState state;
74
  // High priority thread running RealTimeThread()
75
  pthread_t thread;
76
  // Protects vol, volpending and hw_delay
77
  pthread_mutex_t mutex;
78
  // Current volume in the 0..SIO_MAXVOL range
79
  int vol;
80
  // Set to 1 if volumes must be refreshed in the realtime thread
81
  int volpending;
82
  // Number of bytes buffered in the hardware
83
  int hw_delay;
84
  // Temporary buffer where data is stored sndio-compatible format
85
  char* buffer;
86
87
  DISALLOW_COPY_AND_ASSIGN(SndioAudioOutputStream);
88
};
89
90
}  // namespace media
91
92
#endif  // MEDIA_AUDIO_SNDIO_SNDIO_OUTPUT_H_

Return to bug 220230