Add WIP progress sndio support to chrome, developed by jakemsr@ and

with modifications by me.
It is not working yet so you can only enable it by setting the
CHROME_SNDIO environment variable, so by default nothing changes.
I commit this so that other people can work on it too.
This commit is contained in:
robert 2011-05-20 08:35:24 +00:00
parent 2f4780a0dc
commit cb80367c54
6 changed files with 483 additions and 33 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.47 2011/05/19 11:57:37 ajacoutot Exp $
# $OpenBSD: Makefile,v 1.48 2011/05/20 08:35:24 robert Exp $
ONLY_FOR_ARCHS= i386 amd64
@ -7,7 +7,7 @@ COMMENT= Chromium browser
V= 11.0.696.68
DISTNAME= chromium-${V}
REVISION= 4
REVISION= 5
CATEGORIES= www
@ -31,7 +31,7 @@ WANTLIB += gtk-x11-2.0 jpeg m nspr4 pango-1.0 pangocairo-1.0 pangoft2-1.0
WANTLIB += pixman-1 plc4 plds4 png pthread pthread-stubs xcb xml2
WANTLIB += z execinfo bz2 nss3 nssutil3 ssl3 smime3 softokn3 gconf-2
WANTLIB += GL Xxf86vm drm stdc++ xcb-render xcb-shm
WANTLIB += Xtst event xslt vpx kvm>=10.0
WANTLIB += Xtst event xslt vpx kvm>=10.0 sndio
MASTER_SITES= http://build.chromium.org/buildbot/official/ \
http://blade2k.humppa.hu/distfiles/ \

View File

@ -1,19 +1,74 @@
$OpenBSD: patch-media_audio_openbsd_audio_manager_openbsd_cc,v 1.3 2011/04/29 13:18:01 robert Exp $
--- media/audio/openbsd/audio_manager_openbsd.cc.orig Thu Apr 28 11:48:27 2011
+++ media/audio/openbsd/audio_manager_openbsd.cc Thu Apr 28 11:49:20 2011
@@ -4,9 +4,13 @@
$OpenBSD: patch-media_audio_openbsd_audio_manager_openbsd_cc,v 1.4 2011/05/20 08:35:24 robert Exp $
--- media/audio/openbsd/audio_manager_openbsd.cc.orig Sat May 7 11:39:59 2011
+++ media/audio/openbsd/audio_manager_openbsd.cc Thu May 19 16:34:51 2011
@@ -4,14 +4,17 @@
#include "media/audio/openbsd/audio_manager_openbsd.h"
+#include "base/command_line.h"
#include "base/logging.h"
-
-static AudioManagerOpenBSD* g_audio_manager = NULL;
+#include "media/audio/audio_output_dispatcher.h"
-#include "base/logging.h"
+#include "base/sys_info.h"
+#include "media/audio/fake_audio_input_stream.h"
+#include "media/audio/fake_audio_output_stream.h"
+#include "media/audio/openbsd/audio_manager_openbsd.h"
+#include "media/audio/openbsd/sndio_output.h"
+#include "media/base/limits.h"
+#include "media/base/limits.h"
+#include "media/base/media_switches.h"
-static AudioManagerOpenBSD* g_audio_manager = NULL;
-
// Implementation of AudioManager.
bool AudioManagerOpenBSD::HasAudioOutputDevices() {
- NOTIMPLEMENTED();
- return false;
+ return true;
}
bool AudioManagerOpenBSD::HasAudioInputDevices() {
@@ -21,8 +24,17 @@ bool AudioManagerOpenBSD::HasAudioInputDevices() {
AudioOutputStream* AudioManagerOpenBSD::MakeAudioOutputStream(
AudioParameters params) {
- NOTIMPLEMENTED();
- return NULL;
+
+ if (getenv("CHROME_SNDIO") == NULL) {
+ NOTIMPLEMENTED();
+ return NULL;
+ }
+
+ if (params.format == AudioParameters::AUDIO_MOCK) {
+ return FakeAudioOutputStream::MakeFakeStream(params);
+ }
+
+ return new PCMQueueOutAudioOutputStream(this, params);
}
AudioInputStream* AudioManagerOpenBSD::MakeAudioInputStream(
@@ -37,10 +49,6 @@ AudioManagerOpenBSD::AudioManagerOpenBSD() {
AudioManagerOpenBSD::~AudioManagerOpenBSD() {
}
-void AudioManagerOpenBSD::Init() {
- AudioManagerBase::Init();
-}
-
void AudioManagerOpenBSD::MuteAll() {
NOTIMPLEMENTED();
}
@@ -52,4 +60,16 @@ void AudioManagerOpenBSD::UnMuteAll() {
// static
AudioManager* AudioManager::CreateAudioManager() {
return new AudioManagerOpenBSD();
+}
+
+// Called by the stream when it has been released by calling Close().
+void AudioManagerOpenBSD::ReleaseOutputStream(
+ PCMQueueOutAudioOutputStream* stream) {
+ DCHECK(stream);
+ delete stream;
+}
+
+// Called by the stream when it has been released by calling Close().
+void AudioManagerOpenBSD::ReleaseInputStream(PCMQueueInAudioInputStream* stream) {
+ NOTIMPLEMENTED();
}

View File

@ -1,29 +1,39 @@
$OpenBSD: patch-media_audio_openbsd_audio_manager_openbsd_h,v 1.4 2011/04/29 13:18:01 robert Exp $
--- media/audio/openbsd/audio_manager_openbsd.h.orig Tue Apr 26 10:01:05 2011
+++ media/audio/openbsd/audio_manager_openbsd.h Fri Apr 29 09:48:16 2011
@@ -5,8 +5,16 @@
$OpenBSD: patch-media_audio_openbsd_audio_manager_openbsd_h,v 1.5 2011/05/20 08:35:24 robert Exp $
--- media/audio/openbsd/audio_manager_openbsd.h.orig Sat May 7 11:39:59 2011
+++ media/audio/openbsd/audio_manager_openbsd.h Thu May 19 14:20:55 2011
@@ -5,15 +5,16 @@
#ifndef MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
#define MEDIA_AUDIO_OPENBSD_AUDIO_MANAGER_OPENBSD_H_
-#include "media/audio/audio_io.h"
+#include <map>
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread.h"
+#include "base/basictypes.h"
+#include "media/audio/audio_manager_base.h"
+
+class AlsaPcmOutputStream;
+class PCMQueueInAudioInputStream;
+class PCMQueueOutAudioOutputStream;
+
class AudioManagerOpenBSD : public AudioManagerBase {
public:
AudioManagerOpenBSD();
@@ -19,6 +27,7 @@ class AudioManagerOpenBSD : public AudioManagerBase {
- // Call before using a newly created AudioManagerOpenBSD instance.
- virtual void Init();
-
// Implementation of AudioManager.
virtual bool HasAudioOutputDevices();
virtual bool HasAudioInputDevices();
virtual AudioOutputStream* MakeAudioOutputStream(AudioParameters params);
virtual AudioInputStream* MakeAudioInputStream(AudioParameters params);
+
@@ -22,10 +23,12 @@ class AudioManagerOpenBSD : public AudioManagerBase {
virtual void MuteAll();
virtual void UnMuteAll();
- protected:
- virtual ~AudioManagerOpenBSD();
+ void ReleaseOutputStream(PCMQueueOutAudioOutputStream* stream);
+ void ReleaseInputStream(PCMQueueInAudioInputStream* stream);
private:
+ virtual ~AudioManagerOpenBSD();
+
DISALLOW_COPY_AND_ASSIGN(AudioManagerOpenBSD);
};

View File

@ -0,0 +1,272 @@
$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

@ -0,0 +1,89 @@
$OpenBSD: patch-media_audio_openbsd_sndio_output_h,v 1.1 2011/05/20 08:35:24 robert Exp $
--- media/audio/openbsd/sndio_output.h.orig Thu May 19 14:21:02 2011
+++ media/audio/openbsd/sndio_output.h Thu May 19 17:10:23 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/ref_counted.h"
+#include "base/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,16 @@
$OpenBSD: patch-media_media_gyp,v 1.4 2011/04/29 13:18:01 robert Exp $
--- media/media.gyp.orig Tue Apr 26 10:01:05 2011
+++ media/media.gyp Thu Apr 28 11:17:49 2011
@@ -177,6 +177,9 @@
$OpenBSD: patch-media_media_gyp,v 1.5 2011/05/20 08:35:24 robert Exp $
--- media/media.gyp.orig Sat May 7 11:39:59 2011
+++ media/media.gyp Thu May 19 14:20:05 2011
@@ -54,6 +54,8 @@
'audio/linux/alsa_util.h',
'audio/linux/alsa_wrapper.cc',
'audio/linux/alsa_wrapper.h',
+ 'audio/openbsd/sndio_output.cc',
+ 'audio/openbsd/sndio_output.h',
'audio/openbsd/audio_manager_openbsd.cc',
'audio/openbsd/audio_manager_openbsd.h',
'audio/mac/audio_input_mac.cc',
@@ -177,6 +179,9 @@
'link_settings': {
'libraries': [
'-lasound',
@ -11,3 +20,18 @@ $OpenBSD: patch-media_media_gyp,v 1.4 2011/04/29 13:18:01 robert Exp $
],
},
}],
@@ -186,11 +191,14 @@
['exclude', '\\.mm?$' ] ],
'link_settings': {
'libraries': [
+ '-lsndio',
],
},
}],
['OS!="openbsd"', {
'sources!': [
+ 'audio/openbsd/sndio_output.cc',
+ 'audio/openbsd/sndio_output.h',
'audio/openbsd/audio_manager_openbsd.cc',
'audio/openbsd/audio_manager_openbsd.h',
],