[MPlayer-dev-eng] [PATCH] openal output

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Tue Feb 14 20:48:09 CET 2006


Hi,
this adds an OpenAL output method to MPlayer. It is quite useless in the
current form since it is slow and does not support any positioning so everything
will play as mono, but maybe if it is in CVS it will inspire someone
(might be a nice framework for anyone who wants to start playing around
with OpenAL).
Are the build-system parts okay? Should I commit?

Greetings,
Reimar Döffinger
-------------- next part --------------
Index: Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/Makefile,v
retrieving revision 1.339
diff -u -r1.339 Makefile
--- Makefile	12 Feb 2006 08:03:58 -0000	1.339
+++ Makefile	13 Feb 2006 19:26:51 -0000
@@ -87,6 +87,7 @@
 AO_LIBS = $(ARTS_LIB) \
           $(ESD_LIB) \
           $(JACK_LIB) \
+          $(OPENAL_LIB) \
           $(NAS_LIB) \
           $(SGIAUDIO_LIB) \
           $(POLYP_LIB) \
Index: configure
===================================================================
RCS file: /cvsroot/mplayer/main/configure,v
retrieving revision 1.1131
diff -u -r1.1131 configure
--- configure	11 Feb 2006 23:29:51 -0000	1.1131
+++ configure	13 Feb 2006 19:27:34 -0000
@@ -316,6 +316,7 @@
   --disable-esd          disable esd sound support [autodetect]
   --disable-polyp        disable Polypaudio sound support [autodetect]
   --disable-jack         disable JACK sound support [autodetect]
+  --disable-openal       disable OpenAL sound support [autodetect]
   --disable-nas          disable NAS sound support [autodetect]
   --disable-sgiaudio     disable SGI sound support [autodetect]
   --disable-sunaudio     disable Sun sound support [autodetect]
@@ -1508,6 +1509,7 @@
 _esd=auto
 _polyp=auto
 _jack=auto
+_openal=auto
 _libcdio=auto
 _liblzo=auto
 _mad=auto
@@ -1703,6 +1705,8 @@
   --disable-polyp)	_polyp=no		;;
   --enable-jack)	_jack=yes	;;
   --disable-jack)	_jack=no	;;
+  --enable-openal)	_openal=yes	;;
+  --disable-openal)	_openal=no	;;
   --enable-mad)		_mad=yes	;;
   --disable-mad)	_mad=no		;;
   --disable-toolame)	_toolame=no	;;
@@ -4797,6 +4804,31 @@
 fi
 echores "$_jack"
 
+echocheck "OpenAL"
+if test "$_openal" = auto ; then
+  _openal=yes
+cat > $TMPC << EOF
+#include <AL/al.h>
+int main(void) {
+  alSourceQueueBuffers(0, 0, 0);
+//  alGetSourcei(0, AL_SAMPLE_OFFSET, 0);
+  return 0;
+}
+EOF
+  if cc_check -lopenal ; then
+    _ld_openal="-lopenal"
+  else
+    _openal=no
+  fi
+fi
+if test "$_openal" = yes ; then
+  _def_openal='#define USE_OPENAL 1'
+  _aosrc="$_aosrc ao_openal.c"
+  _aomodules="openal $_aomodules"
+else
+  _noaomodules="openal $_noaomodules"
+fi
+echores "$_openal"
 
 echocheck "ALSA audio"
 if test "$_alsa" != no ; then
@@ -7253,6 +7286,8 @@
 POLYP_INC = $_inc_polyp
 JACK_LIB = $_ld_jack
 JACK_INC = $_inc_jack
+OPENAL_LIB = $_ld_openal
+OPENAL_INC = $_inc_openal
 SGIAUDIO_LIB = $_ld_sgiaudio
 
 # input/demuxer/codecs
@@ -7742,6 +7777,7 @@
 $_def_esd_latency
 $_def_polyp
 $_def_jack
+$_def_openal
 $_def_sys_asoundlib_h
 $_def_alsa_asoundlib_h
 $_def_sunaudio
Index: libao2/Makefile
===================================================================
RCS file: /cvsroot/mplayer/main/libao2/Makefile,v
retrieving revision 1.35
diff -u -r1.35 Makefile
--- libao2/Makefile	27 Jan 2006 00:06:38 -0000	1.35
+++ libao2/Makefile	13 Feb 2006 19:30:04 -0000
@@ -17,6 +17,7 @@
           $(ESD_INC) \
           $(EXTRA_INC) \
           $(JACK_INC) \
+          $(OPENAL_INC) \
           $(POLYP_INC) \
           $(SDL_INC) \
           $(X11_INC) \
Index: libao2/ao_openal.c
===================================================================
RCS file: libao2/ao_openal.c
diff -N libao2/ao_openal.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ libao2/ao_openal.c	13 Feb 2006 19:30:05 -0000
@@ -0,0 +1,196 @@
+/* 
+ * ao_openal.c - OpenAL audio output driver for MPlayer
+ *
+ * This driver is under the same license as MPlayer.
+ * (http://www.mplayerhq.hu)
+ *
+ * Copyleft 2006 by Reimar Döffinger (Reimar.Doeffinger at stud.uni-karlsruhe.de)
+ */
+
+#include <inttypes.h>
+#include <AL/alc.h>
+#include <AL/al.h>
+
+#include "config.h"
+#include "mp_msg.h"
+#include "help_mp.h"
+
+#include "audio_out.h"
+#include "audio_out_internal.h"
+#include "libaf/af_format.h"
+#include "osdep/timer.h"
+#include "subopt-helper.h"
+
+static ao_info_t info = 
+{
+  "OpenAL audio output",
+  "openal",
+  "Reimar Döffinger <Reimar.Doeffinger at stud.uni-karlsruhe.de>",
+  ""
+};
+
+LIBAO_EXTERN(openal)
+
+#define MAX_CHANS 6
+#define NUM_BUF 128
+#define CHUNK_SIZE 512
+static ALuint buffers[MAX_CHANS][NUM_BUF];
+static ALuint sources[MAX_CHANS];
+
+static int cur_buf[MAX_CHANS];
+static int unqueue_buf[MAX_CHANS];
+static int16_t *tmpbuf;
+
+
+static int control(int cmd, void *arg) {
+  return CONTROL_UNKNOWN;
+}
+
+/**
+ * \brief print suboption usage help
+ */
+static void print_help(void) {
+  mp_msg(MSGT_AO, MSGL_FATAL,
+          "\n-ao openal commandline help:\n"
+          "Example: mplayer -ao openal\n"
+          "\nOptions:\n"
+        );
+}
+
+static int init(int rate, int channels, int format, int flags) {
+  ALCdevice *dev = NULL;
+  ALCcontext *ctx = NULL;
+  ALint bufrate;
+  int i;
+  opt_t subopts[] = {
+    {NULL}
+  };
+  if (subopt_parse(ao_subdevice, subopts) != 0) {
+    print_help();
+    return 0;
+  }
+  if (channels > MAX_CHANS) {
+    mp_msg(MSGT_AO, MSGL_FATAL, "[OpenAL] Invalid number of channels: %i\n", channels);
+    goto err_out;
+  }
+  dev = alcOpenDevice(NULL);
+  if (!dev) {
+    mp_msg(MSGT_AO, MSGL_FATAL, "[OpenAL] could not open device\n");
+    goto err_out;
+  }
+  ctx = alcCreateContext(dev, NULL);
+  alcMakeContextCurrent(ctx);
+  for (i = 0; i < channels; i++) {
+    cur_buf[i] = 0;
+    unqueue_buf[i] = 0;
+    alGenBuffers(NUM_BUF, buffers[i]);
+  }
+  alGenSources(channels, sources);
+  alSource3f(sources[0], AL_POSITION, 0, 0, 10);
+  ao_data.channels = channels;
+  alGetBufferi(buffers[0][0], AL_FREQUENCY, &bufrate);
+  ao_data.samplerate = rate = bufrate;
+  ao_data.format = AF_FORMAT_S16_NE;
+  ao_data.bps = channels * rate * 2;
+  ao_data.buffersize = CHUNK_SIZE * NUM_BUF;
+  ao_data.outburst = channels * CHUNK_SIZE;
+  tmpbuf = (int16_t *)malloc(CHUNK_SIZE);
+  return 1;
+
+err_out:
+  return 0;
+}
+
+// close audio device
+static void uninit(int immed) {
+  ALCcontext *ctx = alcGetCurrentContext();
+  ALCdevice *dev = alcGetContextsDevice(ctx);
+  free(tmpbuf);
+  if (!immed) {
+    ALint state;
+    alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
+    while (state == AL_PLAYING) {
+      usec_sleep(10000);
+      alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
+    }
+  }
+  reset();
+  alcMakeContextCurrent(NULL);
+  alcDestroyContext(ctx);
+  alcCloseDevice(dev);
+}
+
+static void unqueue_buffers(void) {
+  ALint p;
+  int s, i;
+  for (s = 0;  s < ao_data.channels; s++) {
+    alGetSourcei(sources[s], AL_BUFFERS_PROCESSED, &p);
+    for (i = 0; i < p; i++) {
+      alSourceUnqueueBuffers(sources[s], 1, &buffers[s][unqueue_buf[s]]);
+      unqueue_buf[s] = (unqueue_buf[s] + 1) % NUM_BUF;
+    }
+  }
+}
+
+/**
+ * \brief stop playing and empty buffers (for seeking/pause)
+ */
+static void reset(void) {
+  alSourceRewindv(ao_data.channels, sources);
+  unqueue_buffers();
+}
+
+/**
+ * \brief stop playing, keep buffers (for pause)
+ */
+static void audio_pause(void) {
+  alSourcePausev(ao_data.channels, sources);
+}
+
+/**
+ * \brief resume playing, after audio_pause()
+ */
+static void audio_resume(void) {
+  alSourcePlayv(ao_data.channels, sources);
+}
+
+static int get_space(void) {
+  ALint queued;
+  unqueue_buffers();
+  alGetSourcei(sources[0], AL_BUFFERS_QUEUED, &queued);
+  return (NUM_BUF - queued) * CHUNK_SIZE * ao_data.channels;
+}
+
+/**
+ * \brief write data into buffer and reset underrun flag
+ */
+static int play(void *data, int len, int flags) {
+  ALint state;
+  int i, j, k;
+  int ch;
+  int16_t *d = data;
+  len /= ao_data.outburst;
+  for (i = 0; i < len; i++) {
+    for (ch = 0; ch < ao_data.channels; ch++) {
+      for (j = 0, k = ch; j < CHUNK_SIZE / 2; j++, k += ao_data.channels)
+        tmpbuf[j] = d[k];
+      alBufferData(buffers[ch][cur_buf[ch]], AL_FORMAT_MONO16, tmpbuf,
+                     CHUNK_SIZE, ao_data.samplerate);
+      alSourceQueueBuffers(sources[ch], 1, &buffers[ch][cur_buf[ch]]);
+      cur_buf[ch] = (cur_buf[ch] + 1) % NUM_BUF;
+    }
+    d += ao_data.channels * CHUNK_SIZE / 2;
+  }
+  alGetSourcei(sources[0], AL_SOURCE_STATE, &state);
+  if (state != AL_PLAYING) // checked here in case of an underrun
+    alSourcePlayv(ao_data.channels, sources);
+  return len * ao_data.outburst;
+}
+
+static float get_delay(void) {
+  ALint queued;
+  unqueue_buffers();
+  alGetSourcei(sources[0], AL_BUFFERS_QUEUED, &queued);
+  return queued * CHUNK_SIZE / 2 / (float)ao_data.samplerate;
+}
+
Index: libao2/audio_out.c
===================================================================
RCS file: /cvsroot/mplayer/main/libao2/audio_out.c,v
retrieving revision 1.51
diff -u -r1.51 audio_out.c
--- libao2/audio_out.c	9 Feb 2006 14:07:54 -0000	1.51
+++ libao2/audio_out.c	13 Feb 2006 19:30:06 -0000
@@ -31,6 +31,7 @@
 #ifdef USE_JACK
 extern ao_functions_t audio_out_jack;
 #endif
+extern ao_functions_t audio_out_openal;
 extern ao_functions_t audio_out_null;
 #ifdef HAVE_ALSA5
  extern ao_functions_t audio_out_alsa5;
@@ -120,6 +121,7 @@
 #ifdef HAVE_SDL
         &audio_out_sdl,
 #endif
+        &audio_out_openal,
         &audio_out_null,
 // should not be auto-selected:
 	&audio_out_pcm,


More information about the MPlayer-dev-eng mailing list