1
mirror of https://github.com/mpv-player/mpv synced 2024-10-18 10:25:02 +02:00

-ao NAS support by Tobias Diedrich <ranma@gmx.at>

git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@3277 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
arpi 2001-12-03 01:13:48 +00:00
parent e76248a995
commit 0a2d56ae1b
6 changed files with 366 additions and 1 deletions

View File

@ -14,6 +14,7 @@ zur Zeit diese Treiber:</P>
<TR><TD>&nbsp;&nbsp;</TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>oss</TD><TD>&nbsp;&nbsp;</TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>OSS (ioctl) Treiber</TD></TR> <TR><TD>&nbsp;&nbsp;</TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>oss</TD><TD>&nbsp;&nbsp;</TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>OSS (ioctl) Treiber</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>sdl</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>SDL Treiber (unterstützt Up-/Downsampling, <B>ESD</B>, <B>ARTS</B> usw.)</TD></TR> <TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>sdl</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>SDL Treiber (unterstützt Up-/Downsampling, <B>ESD</B>, <B>ARTS</B> usw.)</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>nas</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>NAS (Network Audio System) Treiber</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>alsa5</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>ALSA 0.5 Treiber</TD></TR> <TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>alsa5</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>ALSA 0.5 Treiber</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>alsa9</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>ALSA 0.9 Treiber (funkioniert, macht aber Probleme -> verwende OSS)</TD></TR> <TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>alsa9</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>ALSA 0.9 Treiber (funkioniert, macht aber Probleme -> verwende OSS)</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>sun</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>SUN Audio-Treiber (/dev/audio) für BSD und Solaris8 Anwender</TD></TR> <TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>sun</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>SUN Audio-Treiber (/dev/audio) für BSD und Solaris8 Anwender</TD></TR>

View File

@ -14,6 +14,7 @@ contains these drivers :</P>
<TR><TD>&nbsp;&nbsp;</TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>oss</TD><TD>&nbsp;&nbsp;</TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>OSS (ioctl) driver</TD></TR> <TR><TD>&nbsp;&nbsp;</TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>oss</TD><TD>&nbsp;&nbsp;</TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>OSS (ioctl) driver</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>sdl</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>SDL driver (supports up/downsampling, <B>ESD</B>, <B>ARTS</B> etc)</TD></TR> <TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>sdl</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>SDL driver (supports up/downsampling, <B>ESD</B>, <B>ARTS</B> etc)</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>nas</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>NAS (Network Audio System) driver</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>alsa5</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>native ALSA 0.5 driver</TD></TR> <TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>alsa5</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>native ALSA 0.5 driver</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>alsa9</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>native ALSA 0.9 driver (works, but has problems -> use OSS)</TD></TR> <TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>alsa9</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>native ALSA 0.9 driver (works, but has problems -> use OSS)</TD></TR>
<TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>sun</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>SUN audio driver (/dev/audio) for BSD and Solaris8 users</TD></TR> <TR><TD></TD><TD VALIGN=top><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>sun</TD><TD></TD><TD><FONT face="Verdana, Arial, Helvetica, sans-serif" size=2>SUN audio driver (/dev/audio) for BSD and Solaris8 users</TD></TR>

View File

@ -34,7 +34,7 @@ CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Iloader -Ilibvo2 $(EXTRA_INC) # -Wall
VO_LIBS = -Llibvo2 -lvo2 $(X_LIB) $(DXR3_LIB) $(GGI_LIB) $(MLIB_LIB) $(PNG_LIB) $(SDL_LIB) $(SVGA_LIB) VO_LIBS = -Llibvo2 -lvo2 $(X_LIB) $(DXR3_LIB) $(GGI_LIB) $(MLIB_LIB) $(PNG_LIB) $(SDL_LIB) $(SVGA_LIB)
endif endif
A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 $(ALSA_LIB) $(MAD_LIB) $(VORBIS_LIB) $(SGIAUDIO_LIB) A_LIBS = -Lmp3lib -lMP3 -Llibac3 -lac3 $(ALSA_LIB) $(NAS_LIB) $(MAD_LIB) $(VORBIS_LIB) $(SGIAUDIO_LIB)
OSDEP_LIBS = -Llinux -losdep OSDEP_LIBS = -Llinux -losdep
PP_LIBS = -Lpostproc -lpostproc PP_LIBS = -Lpostproc -lpostproc

24
configure vendored
View File

@ -646,6 +646,7 @@ _x11=auto
_dga=auto # 1 2 no auto _dga=auto # 1 2 no auto
_xv=auto _xv=auto
_sdl=auto _sdl=auto
_nas=auto
_png=auto _png=auto
_gl=auto _gl=auto
_ggi=auto _ggi=auto
@ -714,6 +715,8 @@ for ac_option do
--disable-xv) _xv=no ;; --disable-xv) _xv=no ;;
--enable-sdl) _sdl=yes ;; --enable-sdl) _sdl=yes ;;
--disable-sdl) _sdl=no ;; --disable-sdl) _sdl=no ;;
--enable-nas) _nas=yes ;;
--disable-nas) _nas=no ;;
--enable-png) _png=yes ;; --enable-png) _png=yes ;;
--disable-png) _png=no ;; --disable-png) _png=no ;;
--enable-gl) _gl=yes ;; --enable-gl) _gl=yes ;;
@ -1768,6 +1771,24 @@ else
fi fi
echores "$_sdl (with $_sdlconfig)" echores "$_sdl (with $_sdlconfig)"
echocheck "NAS"
if test "$_nas" = auto || test "$_nas" = yes ; then
cat > $TMPC << EOF
#include <audio/audiolib.h>
int main(void) { return 0; }
EOF
_nas=no
cc_check -laudio -lX11 -lXt -L$_x11libdir && _nas=yes
fi
if test "$_nas" = yes ; then
_def_nas='#define HAVE_NAS 1'
_ld_nas="-laudio -lX11 -lXt -L$_x11libdir"
_aosrc="$_aosrc ao_nas.c"
_aomodules="nas $_aomodules"
else
_def_nas='#undef HAVE_NAS'
fi
echores "$_nas"
echocheck "DXR3/H+" echocheck "DXR3/H+"
if test "$_dxr3" = auto ; then if test "$_dxr3" = auto ; then
@ -2598,6 +2619,7 @@ AA_LIB = $_ld_aa
# audio output # audio output
ALSA_LIB = $_ld_alsa ALSA_LIB = $_ld_alsa
NAS_LIB = $_ld_nas
MAD_LIB = $_ld_mad MAD_LIB = $_ld_mad
VORBIS_LIB = $_ld_vorbis VORBIS_LIB = $_ld_vorbis
SGIAUDIO_LIB = $_ld_sgiaudio SGIAUDIO_LIB = $_ld_sgiaudio
@ -2779,6 +2801,8 @@ $_def_alsa5
$_def_alsa9 $_def_alsa9
$_def_sunaudio $_def_sunaudio
$_def_sgiaudio $_def_sgiaudio
$_def_nas
/* Enable fast OSD/SUB renderer (looks ugly, but uses less CPU power) */ /* Enable fast OSD/SUB renderer (looks ugly, but uses less CPU power) */
#undef FAST_OSD #undef FAST_OSD

333
libao2/ao_nas.c Normal file
View File

@ -0,0 +1,333 @@
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <audio/audiolib.h>
#include "audio_out.h"
#include "audio_out_internal.h"
#include "afmt.h"
#define FRAG_SIZE 4096
#define FRAG_COUNT 8
#define BUFFER_SIZE FRAG_SIZE * FRAG_COUNT
#define NAS_DEBUG 0
#if NAS_DEBUG == 1
#define DPRINTF(format, args...) fprintf(stderr, format, ## args); \
fflush(stderr)
#else
#define DPRINTF(format, args...)
#endif
static ao_info_t info =
{
"NAS audio output",
"nas",
"Tobias Diedrich",
""
};
static AuServer* aud;
static AuFlowID flow;
static AuDeviceID dev;
static void *client_buffer;
static int client_buffer_size = BUFFER_SIZE;
static int client_buffer_used;
static int server_buffer_size = BUFFER_SIZE;
static int server_buffer_used;
static pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t event_thread;
static int stop_thread;
LIBAO_EXTERN(nas)
static void wait_for_event()
{
AuEvent ev;
AuNextEvent(aud, AuTrue, &ev);
AuDispatchEvent(aud, &ev);
}
static int readBuffer(int num)
{
pthread_mutex_lock(&buffer_mutex);
DPRINTF("readBuffer(): num=%d client=%d/%d server=%d/%d\n",
num,
client_buffer_used, client_buffer_size,
server_buffer_used, server_buffer_size);
if (client_buffer_used == 0) {
DPRINTF("buffer is empty, nothing read.\n");
pthread_mutex_unlock(&buffer_mutex);
return 0;
}
if (client_buffer_used < num)
num = client_buffer_used;
AuWriteElement(aud, flow, 0, num, client_buffer, AuFalse, NULL);
client_buffer_used -= num;
server_buffer_used += num;
memmove(client_buffer, client_buffer + num, client_buffer_used);
pthread_mutex_unlock(&buffer_mutex);
return num;
}
static void writeBuffer(void *data, int len)
{
pthread_mutex_lock(&buffer_mutex);
DPRINTF("writeBuffer(): len=%d client=%d/%d server=%d/%d\n",
len, client_buffer_used, client_buffer_size,
server_buffer_used, server_buffer_size);
memcpy(client_buffer + client_buffer_used, data, len);
client_buffer_used += len;
pthread_mutex_unlock(&buffer_mutex);
if (server_buffer_used < server_buffer_size)
readBuffer(server_buffer_size - server_buffer_used);
}
static void *event_thread_start(void *data)
{
while (!stop_thread) {
wait_for_event();
}
}
static AuBool event_handler(AuServer *aud, AuEvent *ev, AuEventHandlerRec *hnd)
{
switch (ev->type) {
case AuEventTypeElementNotify: {
AuElementNotifyEvent *event = (AuElementNotifyEvent *) ev;
DPRINTF("event_handler(): kind %d state %d->%d reason %d numbytes %d\n",
event->kind,
event->prev_state,
event->cur_state,
event->reason,
event->num_bytes);
switch (event->kind) {
case AuElementNotifyKindLowWater:
server_buffer_used -= event->num_bytes;
readBuffer(event->num_bytes);
break;
case AuElementNotifyKindState:
if ((event->cur_state == AuStatePause) &&
(event->reason != AuReasonUser)) {
// buffer underrun -> refill buffer
server_buffer_used = 0;
readBuffer(server_buffer_size - server_buffer_used);
}
}
}
}
return AuTrue;
}
static AuBool error_handler(AuServer* aud, AuErrorEvent* ev)
{
char s[100];
AuGetErrorText(aud, ev->error_code, s, 100);
fprintf(stderr,"libaudiooss: error [%s]\n"
"error_code: %d\n"
"request_code: %d\n"
"minor_code: %d\n",
s,
ev->error_code,
ev->request_code,
ev->minor_code);
fflush(stderr);
return AuTrue;
}
static AuDeviceID find_device(int nch)
{
int i;
for (i = 0; i < AuServerNumDevices(aud); i++) {
AuDeviceAttributes *dev = AuServerDevice(aud, i);
if ((AuDeviceKind(dev) == AuComponentKindPhysicalOutput) &&
AuDeviceNumTracks(dev) == nch) {
return AuDeviceIdentifier(dev);
}
}
return AuNone;
}
static unsigned char aformat_to_auformat(unsigned int format)
{
switch (format) {
case AFMT_U8: return AuFormatLinearUnsigned8;
case AFMT_S8: return AuFormatLinearSigned8;
case AFMT_U16_LE: return AuFormatLinearUnsigned16LSB;
case AFMT_U16_BE: return AuFormatLinearUnsigned16MSB;
case AFMT_S16_LE: return AuFormatLinearSigned16LSB;
case AFMT_S16_BE: return AuFormatLinearSigned16MSB;
case AFMT_MU_LAW: return AuFormatULAW8;
default: return 0;
}
}
// to set/get/query special features/parameters
static int control(int cmd,int arg){
return -1;
}
// open & setup audio device
// return: 1=success 0=fail
static int init(int rate,int channels,int format,int flags)
{
AuElement elms[3];
AuStatus as;
unsigned char auformat = aformat_to_auformat(format);
int bytes_per_sample;
char *server;
printf("ao2: %d Hz %d chans %s\n",rate,channels,
audio_out_format_name(format));
if (!auformat) {
printf("Unsupported format -> nosound\n");
return 0;
}
client_buffer = malloc(BUFFER_SIZE);
bytes_per_sample = channels * AuSizeofFormat(auformat);
ao_data.samplerate = rate;
ao_data.channels = channels;
ao_data.buffersize = BUFFER_SIZE * 2;
ao_data.outburst = FRAG_SIZE;
ao_data.bps = rate * bytes_per_sample;
if (!bytes_per_sample) {
printf("Zero bytes per sample -> nosound\n");
return 0;
}
if (!(server = getenv("AUDIOSERVER")))
server = getenv("DISPLAY");
if (!server) // default to tcp/localhost:8000
server = "tcp/localhost:8000";
printf("Using audioserver %s\n", server);
aud = AuOpenServer(server, 0, NULL, 0, NULL, NULL);
if (!aud){
printf("Can't open nas audio server -> nosound\n");
return 0;
}
dev = find_device(channels);
if ((dev == AuNone) || (!(flow = AuCreateFlow(aud, NULL)))) {
printf("Can't find a device serving that many channels -> nosound\n");
AuCloseServer(aud);
aud = 0;
return 0;
}
AuMakeElementImportClient(elms, rate, auformat, channels, AuTrue,
BUFFER_SIZE / bytes_per_sample,
(BUFFER_SIZE - FRAG_SIZE) / bytes_per_sample,
0, NULL);
AuMakeElementExportDevice(elms+1, 0, dev, rate,
AuUnlimitedSamples, 0, NULL);
AuSetElements(aud, flow, AuTrue, 2, elms, &as);
if (as != AuSuccess)
printf("AuSetElements returned status %d!\n", as);
AuRegisterEventHandler(aud, AuEventHandlerIDMask |
AuEventHandlerTypeMask,
AuEventTypeElementNotify, flow,
event_handler, (AuPointer) NULL);
AuSetErrorHandler(aud, error_handler);
AuStartFlow(aud, flow, &as);
if (as != AuSuccess)
printf("AuSetElements returned status %d!\n", as);
/*
* Wait for first buffer underrun event
*
* For some weird reason we get a buffer underrun event if we
* don't fill the server buffer fast enough after staring the
* flow. So we just wait for it to happen to be in a sane state.
*/
wait_for_event();
pthread_create(&event_thread, NULL, &event_thread_start, NULL);
return 1;
}
// close audio device
static void uninit(){
stop_thread = 1;
pthread_join(event_thread, NULL);
AuStopFlow(aud, flow, NULL);
AuCloseServer(aud);
aud = 0;
free(client_buffer);
}
// stop playing and empty buffers (for seeking/pause)
static void reset(){
pthread_mutex_lock(&buffer_mutex);
client_buffer_used = 0;
pthread_mutex_unlock(&buffer_mutex);
while (server_buffer_used > 0) {
usleep(1000);
// DPRINTF("used=%d\n", server_buffer_used);
}
}
// stop playing, keep buffers (for pause)
static void audio_pause()
{
// for now, just call reset();
reset();
}
// resume playing, after audio_pause()
static void audio_resume()
{
}
// return: how many bytes can be played without blocking
static int get_space()
{
int result;
pthread_mutex_lock(&buffer_mutex);
result = client_buffer_size - client_buffer_used;
pthread_mutex_unlock(&buffer_mutex);
return result;
}
// plays 'len' bytes of 'data'
// it should round it down to outburst*n
// return: number of bytes played
static int play(void* data,int len,int flags){
writeBuffer(data, len);
// printf("ao_nas: wrote %d bytes of audio data\n", len);
return len;
}
// return: delay in seconds between first and last sample in buffer
static float get_delay()
{
float result;
pthread_mutex_lock(&buffer_mutex);
result = ((float)(client_buffer_used + server_buffer_used)) /
(float)ao_data.bps;
pthread_mutex_unlock(&buffer_mutex);
return result;
}

View File

@ -22,6 +22,9 @@ extern ao_functions_t audio_out_null;
#ifdef HAVE_ESD #ifdef HAVE_ESD
extern ao_functions_t audio_out_esd; extern ao_functions_t audio_out_esd;
#endif #endif
#ifdef HAVE_NAS
extern ao_functions_t audio_out_nas;
#endif
#ifdef HAVE_SDL #ifdef HAVE_SDL
extern ao_functions_t audio_out_sdl; extern ao_functions_t audio_out_sdl;
#endif #endif
@ -60,6 +63,9 @@ ao_functions_t* audio_out_drivers[] =
#ifdef HAVE_ESD #ifdef HAVE_ESD
&audio_out_esd, &audio_out_esd,
#endif #endif
#ifdef HAVE_NAS
&audio_out_nas,
#endif
#ifdef HAVE_SDL #ifdef HAVE_SDL
&audio_out_sdl, &audio_out_sdl,
#endif #endif