Enable audio playback support using sndio.
ok robert@
This commit is contained in:
parent
3b4bcaba13
commit
ea44fb5469
@ -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:
|
||||
|
173
www/chromium/files/sndio_output.cc
Normal file
173
www/chromium/files/sndio_output.cc
Normal 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
|
88
www/chromium/files/sndio_output.h
Normal file
88
www/chromium/files/sndio_output.h
Normal 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_
|
@ -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)
|
@ -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
|
||||
|
@ -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);
|
||||
+}
|
@ -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_
|
@ -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',
|
||||
],
|
||||
}],
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user