[MPlayer-dev-eng] PATCH 1/5: ao_multi
Tobias Diedrich
td at informatik.uni-hannover.de
Sun Dec 9 03:58:04 CET 2001
Hi,
This patch adds a multi output plugin, works like this:
mplayer -channels 4 -ao multi:oss:/dev/dsp,nas:tcp/someserver:8000 -dvd 1
or
mplayer -aop list=surround -ao multi:oss,nas
Limitations:
The synchronization code is not good, you can't specify the same
ao-plugin twice and it's missing sanity-checking, but it worked
well enough in first experiments ^_^;
--
Tobias PGP: 0x9AC7E0BC
-------------- next part --------------
diff -urN main-current/libao2/Makefile main-multi/libao2/Makefile
--- main-current/libao2/Makefile Tue Dec 4 16:43:08 2001
+++ main-multi/libao2/Makefile Sun Dec 9 03:07:14 2001
@@ -4,7 +4,7 @@
LIBNAME = libao2.a
# TODO: moveout ao_sdl.c so it's only used when SDL is detected
-SRCS=afmt.c audio_out.c ao_mpegpes.c ao_null.c ao_pcm.c ao_plugin.c pl_delay.c pl_format.c pl_surround.c $(OPTIONAL_SRCS)
+SRCS=afmt.c audio_out.c ao_mpegpes.c ao_null.c ao_pcm.c ao_multi.c ao_plugin.c pl_delay.c pl_format.c pl_surround.c $(OPTIONAL_SRCS)
OBJS=$(SRCS:.c=.o)
CFLAGS = $(OPTFLAGS) -I. -I.. $(SDL_INC) $(X11_INC) $(EXTRA_INC)
diff -urN main-current/libao2/ao_multi.c main-multi/libao2/ao_multi.c
--- main-current/libao2/ao_multi.c Thu Jan 1 01:00:00 1970
+++ main-multi/libao2/ao_multi.c Sun Dec 9 03:19:04 2001
@@ -0,0 +1,241 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "../config.h"
+#include "audio_out.h"
+#include "audio_out_internal.h"
+#include "afmt.h"
+
+#define BUFFER_SIZE 4096
+
+static ao_info_t info =
+{
+ "Multiple Sound device plugin",
+ "multi",
+ "Tobias Diedrich <td at informatik.uni-hannover.de>",
+ ""
+};
+
+LIBAO_EXTERN(multi)
+
+struct ao_multi_outdev
+{
+ int sync;
+ int16_t *outbuf;
+ ao_functions_t *dev;
+ ao_data_t ao_data;
+};
+
+struct ao_multi
+{
+ int16_t *inbuf;
+ int buffer_len;
+ char *mapping;
+ struct ao_multi_outdev devs[10];
+ ao_data_t ao_data;
+ int numdevs;
+};
+
+static struct ao_multi ao_multi;
+
+// to set/get/query special features/parameters
+static int control(int cmd,int arg){
+ return CONTROL_UNKNOWN;
+}
+
+static ao_functions_t *find_dev(char *dev)
+{
+ int n = 0;
+ while (audio_out_drivers[n] != NULL) {
+ if (strcmp(audio_out_drivers[n]->info->short_name, dev) == 0)
+ return audio_out_drivers[n];
+ n++;
+ }
+ return NULL;
+}
+
+
+// open & setup audio device
+// return: 1=success 0=fail
+static int init(int rate,int channels,int format,int flags)
+{
+ char *args;
+ int n;
+ printf("ao_multi: %d Hz %d chans %s\n",
+ rate,channels,audio_out_format_name(format));
+ if (!ao_subdevice) {
+ printf("You have to specify at least the master output\n"
+ "Try -ao multi:oss:/dev/dsp,oss:/dev/dsp1,mapping=1234\n"
+ "This will enable 4 channel playback with 2 Soundcards\n");
+ }
+ args = ao_subdevice;
+ printf("args=%s\n", args);
+ n=0;
+ while (args) {
+ char *dev = args;
+ char *opts;
+ ao_functions_t *ao;
+
+ args = index(dev, ',');
+ if (args)
+ *args++ = 0;
+
+ opts = index(dev, ':');
+ if (opts)
+ *opts++ = 0;
+
+ printf("ao_multi: dev%d: %s, opts=%s\n",
+ n, dev, opts);
+
+ ao = find_dev(dev);
+ if (!ao) {
+ printf("ao_multi: can't find output plugin: %s\n", dev);
+ return 0;
+ }
+ ao_subdevice = opts;
+ if (!ao->init(rate, 2, format, 0)) {
+ printf("ao_multi: slave plugin init failed -> NOSOUND\n");
+ return 0;
+ }
+ ao_multi.devs[n].ao_data = ao_data;
+ ao_multi.devs[n].dev = ao;
+ ao_multi.devs[n].outbuf = malloc(BUFFER_SIZE + 16);
+
+ n++;
+ }
+ ao_multi.numdevs = n;
+
+ ao_data.channels = channels;
+ ao_data.bps = channels * rate;
+ if (format != AFMT_U8 && format != AFMT_S8)
+ ao_data.bps *= 2;
+
+ ao_multi.buffer_len = ao_multi.numdevs * BUFFER_SIZE;
+ ao_multi.inbuf = malloc(ao_multi.buffer_len);
+
+ ao_multi.ao_data = ao_data;
+ printf("ao_multi: init done, ready to go :-)\n");
+ return 1;
+}
+
+// close plugin
+static void uninit(){
+ int n=0;
+ while (ao_multi.devs[n].dev) {
+ ao_data = ao_multi.devs[n].ao_data;
+ ao_multi.devs[n].dev->uninit();
+ free(ao_multi.devs[n].outbuf);
+ n++;
+ }
+ free(ao_multi.inbuf);
+ ao_data = ao_multi.ao_data;
+}
+
+// empty buffers
+static void reset()
+{
+ int n=0;
+ while (ao_multi.devs[n].dev) {
+ ao_data = ao_multi.devs[n].ao_data;
+ ao_multi.devs[n].dev->reset();
+ n++;
+ }
+ ao_data = ao_multi.ao_data;
+}
+
+static void audio_pause()
+{
+ int n=0;
+ while (ao_multi.devs[n].dev) {
+ ao_data = ao_multi.devs[n].ao_data;
+ ao_multi.devs[n].dev->pause();
+ n++;
+ }
+ ao_data = ao_multi.ao_data;
+}
+
+static void audio_resume()
+{
+ int n=0;
+ while (ao_multi.devs[n].dev) {
+ ao_data = ao_multi.devs[n].ao_data;
+ ao_multi.devs[n].dev->resume();
+ n++;
+ }
+ ao_data = ao_multi.ao_data;
+}
+
+static int get_space()
+{
+ int retval=65536 * 256;
+ int n=0;
+
+// printf("ao_multi: get_space()\n");
+
+ while (ao_multi.devs[n].dev) {
+ int free_space;
+ ao_data = ao_multi.devs[n].ao_data;
+ if ((free_space=ao_multi.devs[n].dev->get_space()) < retval)
+ retval = free_space;
+ n++;
+ }
+ retval -= retval % ao_multi.buffer_len;
+
+ ao_data = ao_multi.ao_data;
+// printf("ao_multi: get_space() retval=%d\n", retval);
+ return retval;
+}
+
+static int play(void* data,int len,int flags)
+{
+ int n,m,dev;
+ int16_t *inbuf = data;
+ m = 0;
+// printf("ao_multi: play(len=%d)\n",len);
+ while (len >= ao_multi.buffer_len) {
+ len -= ao_multi.buffer_len;
+ for (n=0; n<(BUFFER_SIZE >> 2); n++) {
+ for (dev=0; dev<ao_multi.numdevs; dev++) {
+ ao_multi.devs[dev].outbuf[n << 1] = inbuf[m++];
+ ao_multi.devs[dev].outbuf[(n << 1)+1] = inbuf[m++];
+ }
+ }
+ for (dev=0; dev<ao_multi.numdevs; dev++) {
+ ao_data = ao_multi.devs[dev].ao_data;
+ ao_multi.devs[dev].dev->play(ao_multi.devs[dev].outbuf,
+ BUFFER_SIZE + (ao_multi.devs[dev].sync << 2), 0);
+ }
+ }
+ ao_data = ao_multi.ao_data;
+ return (m << 1);
+}
+
+static float get_delay()
+{
+ float retval;
+ int n=1;
+// printf("ao_multi: get_delay()\n");
+
+ ao_data = ao_multi.devs[0].ao_data;
+ retval = ao_multi.devs[0].dev->get_delay();
+ while (ao_multi.devs[n].dev) {
+ float slaveval;
+ ao_data = ao_multi.devs[n].ao_data;
+ slaveval = ao_multi.devs[n].dev->get_delay();
+ if (slaveval < retval) {
+ if (ao_multi.devs[n].sync < 4)
+ ao_multi.devs[n].sync++;
+ } else {
+ if (ao_multi.devs[n].sync > -4)
+ ao_multi.devs[n].sync--;
+ }
+// printf("dev%d delaydiff=%f sync=%d\n", n, slaveval - retval, ao_multi.devs[n].sync);
+ n++;
+ }
+
+ ao_data = ao_multi.ao_data;
+// printf("ao_multi: get_delay() retval=%f\n", retval);
+ return retval;
+}
diff -urN main-current/libao2/audio_out.c main-multi/libao2/audio_out.c
--- main-current/libao2/audio_out.c Mon Dec 3 02:13:14 2001
+++ main-multi/libao2/audio_out.c Sat Dec 8 23:33:37 2001
@@ -41,6 +41,7 @@
extern ao_functions_t audio_out_mpegpes;
extern ao_functions_t audio_out_pss;
extern ao_functions_t audio_out_plugin;
+extern ao_functions_t audio_out_multi;
ao_functions_t* audio_out_drivers[] =
{
@@ -75,6 +76,7 @@
&audio_out_pcm,
&audio_out_mpegpes,
&audio_out_plugin,
+ &audio_out_multi,
// &audio_out_pss,
NULL
};
More information about the MPlayer-dev-eng
mailing list