Enable audio playback support using sndio.

ok robert@
This commit is contained in:
ratchov 2012-11-25 18:57:21 +00:00
parent 3b4bcaba13
commit ea44fb5469
8 changed files with 376 additions and 379 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.110 2012/11/07 06:59:45 robert Exp $
# $OpenBSD: Makefile,v 1.111 2012/11/25 18:57:21 ratchov Exp $
ONLY_FOR_ARCHS= i386 amd64
@ -6,6 +6,7 @@ COMMENT= Chromium browser
V= 23.0.1271.64
DISTNAME= chromium-${V}
REVISION= 0
CATEGORIES= www
@ -99,6 +100,7 @@ GYP_DEFS= -Duse_system_bzip2=1 \
-Denable_webrtc=0 \
-Denable_one_click_signin=1 \
-Duse_kerberos=0 \
-Duse_sndio=1 \
-DOS=openbsd
pre-configure:
@ -110,6 +112,8 @@ pre-configure:
.endfor
@cp -R ${WRKSRC}/third_party/libvpx/source/config/linux \
${WRKSRC}/third_party/libvpx/source/config/openbsd
@mkdir -p ${WRKSRC}/media/audio/sndio
@cp files/sndio_output.{cc,h} ${WRKSRC}/media/audio/sndio
# gyp_chromium generates all the Makefiles from gyp
do-configure:

View File

@ -0,0 +1,173 @@
// 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 "media/audio/audio_parameters.h"
#include "media/audio/audio_manager_base.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 * self->params.GetBytesPerFrame();
}
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)),
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
count = source->OnMoreData(audio_bus.get(), AudioBuffersState(0, hw_delay));
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

View File

@ -0,0 +1,88 @@
// 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 "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
scoped_ptr<AudioBus> audio_bus;
// 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_

View File

@ -1,11 +0,0 @@
--- media/audio/pulse/pulse_output.h.orig Wed Oct 31 20:01:19 2012
+++ media/audio/pulse/pulse_output.h Tue Nov 6 22:45:35 2012
@@ -28,7 +28,7 @@
namespace media {
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_FREEBSD)
class AudioManagerLinux;
typedef AudioManagerLinux AudioManagerPulse;
#elif defined(OS_OPENBSD)

View File

@ -1,7 +1,56 @@
$OpenBSD: patch-media_audio_openbsd_audio_manager_openbsd_cc,v 1.11 2012/11/07 06:59:45 robert Exp $
$OpenBSD: patch-media_audio_openbsd_audio_manager_openbsd_cc,v 1.12 2012/11/25 18:57:21 ratchov Exp $
--- media/audio/openbsd/audio_manager_openbsd.cc.orig Wed Oct 31 20:01:19 2012
+++ media/audio/openbsd/audio_manager_openbsd.cc Tue Nov 6 22:45:35 2012
@@ -57,26 +57,26 @@ void AudioManagerOpenBSD::Init() {
+++ media/audio/openbsd/audio_manager_openbsd.cc Thu Nov 22 08:53:57 2012
@@ -4,43 +4,23 @@
#include "media/audio/openbsd/audio_manager_openbsd.h"
-#include "base/command_line.h"
-#include "base/stl_util.h"
#include "media/audio/audio_output_dispatcher.h"
-#if defined(USE_PULSEAUDIO)
-#include "media/audio/pulse/pulse_output.h"
-#endif
+#include "media/audio/sndio/sndio_output.h"
#include "media/base/limits.h"
#include "media/base/media_switches.h"
-#include <fcntl.h>
-
namespace media {
// Maximum number of output streams that can be open simultaneously.
-static const int kMaxOutputStreams = 50;
+static const int kMaxOutputStreams = 4;
-// Implementation of AudioManager.
-static bool HasAudioHardware() {
- int fd;
- const char *file;
-
- if ((file = getenv("AUDIOCTLDEVICE")) == 0 || *file == '\0')
- file = "/dev/audioctl";
-
- if ((fd = open(file, O_RDONLY)) < 0)
- return false;
-
- close(fd);
+bool AudioManagerOpenBSD::HasAudioOutputDevices() {
return true;
}
-bool AudioManagerOpenBSD::HasAudioOutputDevices() {
- return HasAudioHardware();
-}
-
bool AudioManagerOpenBSD::HasAudioInputDevices() {
- return HasAudioHardware();
+ // not implemented yet
+ return false;
}
AudioManagerOpenBSD::AudioManagerOpenBSD() {
@@ -57,40 +37,33 @@ void AudioManagerOpenBSD::Init() {
AudioOutputStream* AudioManagerOpenBSD::MakeLinearOutputStream(
const AudioParameters& params) {
@ -32,3 +81,18 @@ $OpenBSD: patch-media_audio_openbsd_audio_manager_openbsd_cc,v 1.11 2012/11/07 0
NOTIMPLEMENTED();
return NULL;
}
AudioOutputStream* AudioManagerOpenBSD::MakeOutputStream(
const AudioParameters& params) {
-#if defined(USE_PULSEAUDIO)
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUsePulseAudio)) {
- return new PulseAudioOutputStream(params, this);
- }
-#endif
-
- NOTIMPLEMENTED();
- return NULL;
+ return new SndioAudioOutputStream(params, this);
}
// static

View File

@ -1,272 +0,0 @@
$OpenBSD: patch-media_audio_openbsd_sndio_output_cc,v 1.1 2011/05/20 08:35:24 robert Exp $
--- media/audio/openbsd/sndio_output.cc.orig Thu May 19 14:21:00 2011
+++ media/audio/openbsd/sndio_output.cc Thu May 19 17:15:21 2011
@@ -0,0 +1,268 @@
+// Copyright (c) 2010 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/openbsd/sndio_output.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "media/audio/audio_util.h"
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+
+#include <poll.h>
+#include <errno.h>
+
+using base::Time;
+using base::TimeDelta;
+
+namespace {
+
+// A custom data structure to store information an AudioQueue buffer.
+struct AudioQueueUserData {
+ AudioQueueUserData() : empty_buffer(false) {}
+ bool empty_buffer;
+};
+
+} // namespace
+
+// Overview of operation:
+// 1) An object of PCMQueueOutAudioOutputStream is created by the AudioManager
+// factory: audio_man->MakeAudioStream(). This just fills some structure.
+// 2) Next some thread will call Open(), at that point the underliying OS
+// queue is created and the audio buffers allocated.
+// 3) Then some thread will call Start(source) At this point the source will be
+// called to fill the initial buffers in the context of that same thread.
+// Then the OS queue is started which will create its own thread which
+// periodically will call the source for more data as buffers are being
+// consumed.
+// 4) At some point some thread will call Stop(), which we handle by directly
+// stoping the OS queue.
+// 5) One more callback to the source could be delivered in in the context of
+// the queue's own thread. Data, if any will be discared.
+// 6) The same thread that called stop will call Close() where we cleanup
+// and notifiy the audio manager, which likley will destroy this object.
+
+PCMQueueOutAudioOutputStream::PCMQueueOutAudioOutputStream(
+ AudioManagerOpenBSD* manager, AudioParameters params)
+ : sndio_hdl_(),
+ sndio_par_(),
+ source_(NULL),
+ manager_(manager),
+ silence_bytes_(0),
+ volume_(1),
+ hw_pos_(0),
+ sw_pos_(0),
+ buffer_(NULL),
+ buffer_size_(0),
+ thread_("PCMQueueOutAudioOutputStreamThread") {
+
+ DCHECK(manager_);
+
+ sio_initpar(&sndio_par_);
+ sndio_par_.rate = params.sample_rate;
+ sndio_par_.bits = params.bits_per_sample;
+ sndio_par_.le = SIO_LE_NATIVE;
+ sndio_par_.pchan = params.channels;
+ sndio_par_.sig = (params.bits_per_sample == 8) ? 0 :1;
+
+ packet_size_ = params.GetPacketSize();
+
+ AddRef();
+}
+
+PCMQueueOutAudioOutputStream::~PCMQueueOutAudioOutputStream() {
+}
+
+bool PCMQueueOutAudioOutputStream::Open() {
+ sndio_hdl_ = sio_open(NULL, SIO_PLAY, 0);
+ if (!sndio_hdl_) {
+ printf("failed to open audio device\n");
+ return false;
+ }
+
+ if (!sio_setpar(sndio_hdl_, &sndio_par_) ||
+ !sio_getpar(sndio_hdl_, &sndio_par_)) {
+ sio_close(sndio_hdl_);
+ printf("failed to set configuration\n");
+ return false;
+ }
+
+ buffer_size_ = sndio_par_.bufsz * sndio_par_.bps * sndio_par_.pchan;
+ buffer_ = (uint8 *)malloc(buffer_size_);
+ if (!buffer_) {
+ printf("could not allocate buffer for sndio\n");
+ return false;
+ }
+
+ return true;
+}
+
+void PCMQueueOutAudioOutputStream::Close() {
+ if (buffer_)
+ free(buffer_);
+ if (sndio_hdl_)
+ sio_close(sndio_hdl_);
+}
+
+void PCMQueueOutAudioOutputStream::Stop() {
+ thread_.Stop();
+ if (sndio_hdl_ != NULL)
+ sio_stop(sndio_hdl_);
+}
+
+void PCMQueueOutAudioOutputStream::SetVolume(double volume) {
+ NOTIMPLEMENTED();
+}
+
+void PCMQueueOutAudioOutputStream::GetVolume(double* volume) {
+ NOTIMPLEMENTED();
+}
+
+void PCMQueueOutAudioOutputStream::RenderCallback(void* p_this) {
+ PCMQueueOutAudioOutputStream* audio_stream =
+ static_cast<PCMQueueOutAudioOutputStream*>(p_this);
+ size_t w;
+ int n;
+ struct pollfd pfd;
+
+ AudioSourceCallback* source = audio_stream->source_;
+ if (!source)
+ return;
+
+// make sure callbacks have been called
+// XXX can't do this here, since we're called from the onmove callback
+// XXX do we need a thread to do this, and to make sure we don't underrun???
+ n = sio_pollfd(audio_stream->sndio_hdl_, &pfd, POLLOUT);
+ while (poll(&pfd, n, 0) < 0 && errno == EINTR)
+ ; // nothing
+ sio_revents(audio_stream->sndio_hdl_, &pfd);
+
+ if (audio_stream->used_ < 0) {
+ printf("used_ < 0!!\n");
+ goto silence;
+ audio_stream->used_ = 0;
+ }
+
+ printf("audio_stream->filled_ = %d\n", audio_stream->filled_);
+ if (audio_stream->filled_ > audio_stream->buffer_avail_) {
+ printf("audio_stream->filled_ > avail!\n");
+ audio_stream->filled_ = audio_stream->buffer_avail_;
+ }
+ if (!audio_stream->filled_) {
+ return;
+ audio_stream->filled_ = audio_stream->hw_pos_ - audio_stream->sw_pos_;
+ if (audio_stream->filled_ > audio_stream->buffer_size_)
+ audio_stream->filled_ = audio_stream->buffer_size_;
+ else if (1 == 0) {
+silence:
+ audio_stream->filled_ = audio_stream->buffer_size_;
+ }
+ memset(audio_stream->buffer_, 0, audio_stream->filled_);
+ }
+ printf("audio_stream->filled_ = %d\n", audio_stream->filled_);
+ w = sio_write(audio_stream->sndio_hdl_, audio_stream->buffer_, audio_stream->filled_);
+ if (!w) {
+ printf("sndio wrote 0 bytes\n");
+ }
+ audio_stream->sw_pos_ += w;
+}
+
+void PCMQueueOutAudioOutputStream::Start(AudioSourceCallback* callback) {
+ PCMQueueOutAudioOutputStream* audio_stream =
+ static_cast<PCMQueueOutAudioOutputStream*>(this);
+ DCHECK(!thread_.IsRunning());
+ last_callback_time_ = Time::Now();
+ DCHECK(callback);
+ source_ = callback;
+ int w;
+
+ sw_pos_ = hw_pos_ = 0;
+
+ sio_onmove(sndio_hdl_, onmove_callback, this);
+
+ if (!sio_start(sndio_hdl_)) {
+ printf("could not start sndio\n");
+ return;
+ }
+
+ thread_.Start();
+ thread_.message_loop()->PostDelayedTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &PCMQueueOutAudioOutputStream::DoCallback),
+ callback_interval_ms_);
+
+ printf("buffer_size_ = %d\n", buffer_size_);
+
+ /* we want to fill the buffer with silence, to be sure it gets
+ * filled and thus playback actually starts, and we start getting more
+ * onmove callbacks to keep us going.
+ */
+ memset(buffer_, 0, buffer_size_);
+
+ w = sio_write(sndio_hdl_, buffer_, buffer_size_);
+ if (!w || sio_eof(sndio_hdl_)) {
+ printf("sio_write error: wrote %d bytes\n", w);
+ return;
+ }
+ sw_pos_ += w;
+
+ while (sw_pos_ <= buffer_size_) {
+ audio_stream->filled_ = source_->OnMoreData(this, buffer_, buffer_size_,
+ AudioBuffersState(0, sw_pos_));
+ printf("%s: audio_stream->filled_=%d\n", __func__, audio_stream->filled_);
+ w = sio_write(sndio_hdl_, buffer_, audio_stream->filled_);
+ if (!w || sio_eof(sndio_hdl_)) {
+ printf("sio_write error: wrote %d bytes\n", w);
+ return;
+ }
+ sw_pos_ += w;
+ }
+}
+
+void PCMQueueOutAudioOutputStream::onmove_callback(void *p_this, int delta) {
+ PCMQueueOutAudioOutputStream* audio_stream =
+ static_cast<PCMQueueOutAudioOutputStream*>(p_this);
+ printf("delta = %d\n", delta);
+
+ audio_stream->hw_pos_ += delta *
+ audio_stream->sndio_par_.bps * audio_stream->sndio_par_.pchan;
+}
+
+void PCMQueueOutAudioOutputStream::DoCallback() {
+ PCMQueueOutAudioOutputStream* audio_stream =
+ static_cast<PCMQueueOutAudioOutputStream*>(this);
+
+ int max;
+
+ audio_stream->used_ = (audio_stream->hw_pos_ < 0) ? audio_stream->sw_pos_ :
+ audio_stream->sw_pos_ - audio_stream->hw_pos_;
+
+ audio_stream->buffer_avail_ = audio_stream->buffer_size_ - audio_stream->used_;
+ printf("used_ = %d, size = %d avail = %d\n",
+ audio_stream->used_, audio_stream->buffer_size_, audio_stream->buffer_avail_);
+
+ max = audio_stream->buffer_avail_ > 0 ? audio_stream->buffer_avail_ :
+ audio_stream->buffer_size_;
+ audio_stream->filled_ = audio_stream->source_->OnMoreData(audio_stream, audio_stream->buffer_, max,
+ AudioBuffersState(audio_stream->used_, 0));
+
+ Time now = Time::Now();
+ int64 next_callback_ms = (last_callback_time_ +
+ TimeDelta::FromMilliseconds(callback_interval_ms_ * 2) -
+ now).InMilliseconds();
+ // If we are falling behind, try to catch up as much as we can in the next
+ // callback.
+ if (next_callback_ms < 0)
+ next_callback_ms = 0;
+
+ last_callback_time_ = now;
+
+ thread_.message_loop()->PostDelayedTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &PCMQueueOutAudioOutputStream::DoCallback),
+ next_callback_ms);
+
+ if (buffer_avail_)
+ RenderCallback(this);
+}

View File

@ -1,89 +0,0 @@
$OpenBSD: patch-media_audio_openbsd_sndio_output_h,v 1.2 2011/06/08 20:36:56 robert Exp $
--- media/audio/openbsd/sndio_output.h.orig Wed Jun 8 09:58:36 2011
+++ media/audio/openbsd/sndio_output.h Wed Jun 8 17:03:54 2011
@@ -0,0 +1,85 @@
+// Copyright (c) 2010 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_OUTPUT_OPENBSD_H_
+#define MEDIA_AUDIO_OPENBSD_AUDIO_OUTPUT_OPENBSD_H_
+
+#include <sndio.h>
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread.h"
+#include "base/time.h"
+#include "media/audio/audio_io.h"
+#include "media/audio/audio_parameters.h"
+
+class AudioManagerOpenBSD;
+
+// Implementation of AudioOuputStream for OpenBSD OS X using the audio queue service
+// present in OS 10.5 and later. Audioqueue is the successor to the SoundManager
+// services but it is supported in 64 bits.
+class PCMQueueOutAudioOutputStream :
+ public AudioOutputStream,
+ public base::RefCountedThreadSafe<PCMQueueOutAudioOutputStream> {
+ public:
+ // The ctor takes all the usual parameters, plus |manager| which is the
+ // the audio manager who is creating this object.
+ PCMQueueOutAudioOutputStream(AudioManagerOpenBSD* manager,
+ AudioParameters params);
+ // The dtor is typically called by the AudioManager only and it is usually
+ // triggered by calling AudioOutputStream::Close().
+ virtual ~PCMQueueOutAudioOutputStream();
+
+ // Implementation of AudioOutputStream.
+ virtual bool Open();
+ virtual void Close();
+ virtual void Start(AudioSourceCallback* callback);
+ virtual void Stop();
+ virtual void SetVolume(double volume);
+ virtual void GetVolume(double* volume);
+
+ private:
+ // Give RefCountedThreadSafe access our destructor.
+ friend class base::RefCountedThreadSafe<PCMQueueOutAudioOutputStream>;
+
+ // Called when an error occurs.
+ void HandleError(int err);
+
+ static void RenderCallback(void* p_this);
+ void DoCallback();
+ static void onmove_callback(void *data, int);
+
+ struct sio_hdl *sndio_hdl_;
+ struct sio_par sndio_par_;
+
+ // Pointer to the object that will provide the audio samples.
+ AudioSourceCallback* source_;
+ // Our creator, the audio manager needs to be notified when we close.
+ AudioManagerOpenBSD* manager_;
+ // Packet size in bytes.
+ uint32 packet_size_;
+ // Number of bytes for making a silence buffer.
+ int silence_bytes_;
+ // Volume level from 0 to 1.
+ float volume_;
+
+ int32 hw_pos_;
+ int32 sw_pos_;
+
+ uint8 *buffer_;
+ uint32 buffer_size_;
+ uint32 buffer_avail_;
+ uint32 used_;
+ uint32 filled_;
+
+ base::Thread thread_;
+ base::Time last_callback_time_;
+ int callback_interval_ms_;
+
+ DISALLOW_COPY_AND_ASSIGN(PCMQueueOutAudioOutputStream);
+};
+
+#endif // MEDIA_AUDIO_OPENBSD_AUDIO_OUTPUT_OPENBSD_H_

View File

@ -1,7 +1,25 @@
$OpenBSD: patch-media_media_gyp,v 1.15 2012/11/07 06:59:45 robert Exp $
$OpenBSD: patch-media_media_gyp,v 1.16 2012/11/25 18:57:21 ratchov Exp $
--- media/media.gyp.orig Wed Oct 31 20:01:20 2012
+++ media/media.gyp Tue Nov 6 22:45:35 2012
@@ -433,6 +433,7 @@
+++ media/media.gyp Thu Nov 15 12:02:41 2012
@@ -7,6 +7,8 @@
'chromium_code': 1,
# Override to dynamically link the PulseAudio library.
'use_pulseaudio%': 0,
+ # Override to dynamically link the sndio library.
+ 'use_sndioaudio%': 0,
# Override to dynamically link the cras (ChromeOS audio) library.
'use_cras%': 0,
'conditions': [
@@ -133,6 +135,8 @@
'audio/scoped_loop_observer.h',
'audio/simple_sources.cc',
'audio/simple_sources.h',
+ 'audio/sndio/sndio_output.cc',
+ 'audio/sndio/sndio_output.h',
'audio/win/audio_low_latency_input_win.cc',
'audio/win/audio_low_latency_input_win.h',
'audio/win/audio_low_latency_output_win.cc',
@@ -433,6 +437,7 @@
}],
['OS=="openbsd"', {
'sources/': [ ['exclude', '/alsa_' ],
@ -9,3 +27,25 @@ $OpenBSD: patch-media_media_gyp,v 1.15 2012/11/07 06:59:45 robert Exp $
['exclude', '/audio_manager_linux' ] ],
'link_settings': {
'libraries': [
@@ -496,6 +501,21 @@
'sources!': [
'audio/pulse/pulse_output.cc',
'audio/pulse/pulse_output.h',
+ ],
+ }],
+ ['use_sndio == 1', {
+ 'link_settings': {
+ 'libraries': [
+ '-lsndio',
+ ],
+ },
+ 'defines': [
+ 'USE_SNDIO',
+ ],
+ }, { # else: use_sndio == 0
+ 'sources!': [
+ 'audio/sndio/sndio_output.cc',
+ 'audio/sndio/sndio_output.h',
],
}],
],