[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