Commit 4cff6916 authored by Pierre Baillet's avatar Pierre Baillet

- Added SDL sound support. Sounds a bit laggy sometimes but my streams are ill.

  please try.
- modified configure.in and all that stuff. Re-run configure
- SDL audio, video and interface are all part of the same .so now.
- remove YUV old files :->
parent 3a8481df
......@@ -291,7 +291,8 @@ PLUGIN_BEOS = plugins/beos/beos.o \
plugins/beos/vout_beos.o
PLUGIN_DSP = plugins/dsp/dsp.o \
plugins/dsp/aout_dsp.o \
plugins/dsp/aout_dsp.o
PLUGIN_DUMMY = plugins/dummy/dummy.o \
plugins/dummy/aout_dummy.o \
......@@ -311,9 +312,8 @@ PLUGIN_GGI = plugins/ggi/ggi.o \
PLUGIN_SDL = plugins/sdl/sdl.o \
plugins/sdl/intf_sdl.o \
plugins/sdl/vout_sdl.o
# plugins/sdl/video_yuv.o \
# plugins/sdl/video_yuvall.o
plugins/sdl/vout_sdl.o \
plugins/sdl/aout_sdl.o
PLUGIN_NULL = plugins/null/null.o
......
/*****************************************************************************
* aout_sdl.c : audio sdl functions library
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Pierre Baillet <oct@zoy.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <errno.h> /* ENOMEM */
#include <fcntl.h> /* open(), O_WRONLY */
#include <sys/ioctl.h> /* ioctl() */
#include <string.h> /* strerror() */
#include <unistd.h> /* write(), close() */
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include "SDL/SDL.h" /* SDL base include */
#include "config.h"
#include "common.h" /* boolean_t, byte_t */
#include "threads.h"
#include "mtime.h"
#include "plugins.h"
#include "audio_output.h" /* aout_thread_t */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "main.h"
#include "modules.h"
/*****************************************************************************
* aout_sys_t: dsp audio output method descriptor
*****************************************************************************
* This structure is part of the audio output thread descriptor.
* It describes the dsp specific properties of an audio device.
*****************************************************************************/
/* the overflow limit is used to prevent the fifo from growing too big */
#define OVERFLOWLIMIT 100000
typedef struct aout_sys_s
{
byte_t * audio_buf;
int i_audio_end;
} aout_sys_t;
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static int aout_Probe ( probedata_t *p_data );
static int aout_Open ( aout_thread_t *p_aout );
static int aout_SetFormat ( aout_thread_t *p_aout );
static long aout_GetBufInfo ( aout_thread_t *p_aout, long l_buffer_info );
static void aout_Play ( aout_thread_t *p_aout,
byte_t *buffer, int i_size );
static void aout_Close ( aout_thread_t *p_aout );
static void SDL_aout_callback(void *userdata, Uint8 *stream, int len);
/*****************************************************************************
* Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much.
*****************************************************************************/
void aout_getfunctions( function_list_t * p_function_list )
{
p_function_list->pf_probe = aout_Probe;
p_function_list->functions.aout.pf_open = aout_Open;
p_function_list->functions.aout.pf_setformat = aout_SetFormat;
p_function_list->functions.aout.pf_getbufinfo = aout_GetBufInfo;
p_function_list->functions.aout.pf_play = aout_Play;
p_function_list->functions.aout.pf_close = aout_Close;
}
/*****************************************************************************
* aout_Probe: probes the audio device and return a score
*****************************************************************************
* This function tries to open the dps and returns a score to the plugin
* manager so that it can select the best plugin.
*****************************************************************************/
static int aout_Probe( probedata_t *p_data )
{
SDL_AudioSpec *desired, *obtained;
/* Start AudioSDL */
if( SDL_Init(SDL_INIT_AUDIO) != 0)
intf_ErrMsgImm( "aout_Probe: SDL init error: %s", SDL_GetError() );
/* asks for a minimum audio spec so that we are sure the dsp exists */
desired = (SDL_AudioSpec *)malloc( sizeof(SDL_AudioSpec) );
obtained = (SDL_AudioSpec *)malloc( sizeof(SDL_AudioSpec) );
desired->freq = 11025; /* frequency */
desired->format = AUDIO_U8; /* unsigned 8 bits */
desired->channels = 2; /* mono */
desired->callback = SDL_aout_callback; /* no callback function yet */
desired->userdata = NULL; /* null parm for callback */
desired->samples = 4096;
/* If we were unable to open the device, there is no way we can use
* the plugin. Return a score of 0. */
if(SDL_OpenAudio( desired, obtained ) < 0)
{
SDL_CloseAudio();
intf_ErrMsgImm( "aout_Probe: aout sdl error : %s", SDL_GetError() );
return( 0 );
}
/* Otherwise, there are good chances we can use this plugin, return 100. */
SDL_CloseAudio();
return( 100 );
}
/*****************************************************************************
* aout_Open: opens the audio device (the digital sound processor)
*****************************************************************************
* This function opens the dsp as a usual non-blocking write-only file, and
* modifies the p_aout->i_fd with the file's descriptor.
*****************************************************************************/
static int aout_Open( aout_thread_t *p_aout )
{
SDL_AudioSpec *desired;
int i_stereo = p_aout->b_stereo?2:1;
/* asks for a minimum audio spec so that we are sure the dsp exists */
desired = (SDL_AudioSpec *)malloc( sizeof(SDL_AudioSpec) );
/* Allocate structure */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
{
intf_ErrMsg("aout_Open error: %s", strerror(ENOMEM) );
return( 1 );
}
p_aout->p_sys->i_audio_end = 0;
p_aout->p_sys->audio_buf = NULL;
/* Initialize some variables */
p_aout->psz_device = 0;
p_aout->i_format = AOUT_FORMAT_DEFAULT;
p_aout->i_channels = 1 + main_GetIntVariable( AOUT_STEREO_VAR,
AOUT_STEREO_DEFAULT );
p_aout->l_rate = main_GetIntVariable( AOUT_RATE_VAR,
AOUT_RATE_DEFAULT );
desired->freq = p_aout->l_rate;
/* TODO: write conversion beetween AOUT_FORMAT_DEFAULT
* AND AUDIO* from SDL. */
desired->format = AUDIO_S16LSB; /* stereo 16 bits */
desired->channels = i_stereo;
desired->callback = SDL_aout_callback;
desired->userdata = p_aout->p_sys;
desired->samples = 2048;
/* Open the sound device
* we just ask the SDL to wrap at the good frequency if the one we
* ask for is unavailable. This is done by setting the second parar
* to NULL
*/
if( SDL_OpenAudio(desired,NULL) < 0 )
{
intf_ErrMsgImm( "aout_Open error: can't open audio device: %s",
SDL_GetError() );
return( -1 );
}
SDL_PauseAudio(0);
return( 0 );
}
/*****************************************************************************
* aout_SetFormat: resets the dsp and sets its format
*****************************************************************************
* This functions resets the DSP device, tries to initialize the output
* format with the value contained in the dsp structure, and if this value
* could not be set, the default value returned by ioctl is set. It then
* does the same for the stereo mode, and for the output rate.
*****************************************************************************/
static int aout_SetFormat( aout_thread_t *p_aout )
{
/* TODO: finish and clean this */
SDL_AudioSpec *desired;
int i_stereo = p_aout->b_stereo?2:1;
desired = (SDL_AudioSpec *)malloc( sizeof(SDL_AudioSpec) );
/* i_format = p_aout->i_format;
*/
desired->freq = p_aout->l_rate; /* Set the output rate */
desired->format = AUDIO_S16LSB; /* stereo 16 bits */
desired->channels = i_stereo;
desired->callback = SDL_aout_callback;
desired->userdata = p_aout->p_sys;
desired->samples = 2048;
/* Open the sound device */
SDL_PauseAudio(1);
SDL_CloseAudio();
if( SDL_OpenAudio(desired,NULL) < 0 )
return( -1 );
SDL_PauseAudio(0);
return(0);
}
/*****************************************************************************
* aout_GetBufInfo: buffer status query
*****************************************************************************
* returns the number of bytes in the audio buffer compared to the size of
* l_buffer_limit...
*****************************************************************************/
static long aout_GetBufInfo( aout_thread_t *p_aout, long l_buffer_limit )
{
return( p_aout->p_sys->i_audio_end-l_buffer_limit);
}
static void SDL_aout_callback(void *userdata, byte_t *stream, int len)
{
struct aout_sys_s * p_sys = userdata;
int end = p_sys->i_audio_end;
if(end > OVERFLOWLIMIT)
{
intf_ErrMsgImm("aout SDL_aout_callback: Overflow.");
free(p_sys->audio_buf);
p_sys->audio_buf = NULL;
p_sys->i_audio_end = 0;
end = 0;
// we've gone to slow, increase output freq
}
/* if we are not in underrun */
if(end>len)
{
memcpy(stream, p_sys->audio_buf, len);
memmove(p_sys->audio_buf, &(p_sys->audio_buf[len]), end-len);
p_sys->audio_buf = realloc(p_sys->audio_buf, end-len);
p_sys->i_audio_end -= len;
}
}
/*****************************************************************************
* aout_Play: plays a sound samples buffer
*****************************************************************************
* This function writes a buffer of i_length bytes in the dsp
*****************************************************************************/
static void aout_Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
{
byte_t * audio_buf = p_aout->p_sys->audio_buf;
SDL_LockAudio(); /* Stop callbacking */
audio_buf = realloc(audio_buf, p_aout->p_sys->i_audio_end + i_size);
memcpy(&(audio_buf[p_aout->p_sys->i_audio_end]), buffer, i_size);
p_aout->p_sys->i_audio_end += i_size;
p_aout->p_sys->audio_buf = audio_buf;
SDL_UnlockAudio(); /* go on callbacking */
}
/*****************************************************************************
* aout_Close: closes the dsp audio device
*****************************************************************************/
static void aout_Close( aout_thread_t *p_aout )
{
SDL_LockAudio(); /* Stop callbacking */
SDL_PauseAudio(1); /* pause audio */
if(p_aout->p_sys->audio_buf != NULL) /* do we have a buffer now ? */
{
free(p_aout->p_sys->audio_buf);
}
free(p_aout->p_sys); /* Close the Output. */
SDL_CloseAudio();
}
......@@ -22,6 +22,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#define MODULE_NAME sdl
/*****************************************************************************
* Preamble
*****************************************************************************/
......@@ -41,15 +43,27 @@
#include "video.h"
#include "video_output.h"
/* audio includes */
#include "modules.h"
#include "modules_inner.h"
/*****************************************************************************
* Building configuration tree
*****************************************************************************/
MODULE_CONFIG_START
ADD_WINDOW( "Configuration for sdl module" )
ADD_COMMENT( "For now, the sdl module cannot be configured" )
MODULE_CONFIG_END
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
static void vout_GetPlugin( p_vout_thread_t p_vout );
static void intf_GetPlugin( p_intf_thread_t p_intf );
#if 0
static void yuv_GetPlugin( p_vout_thread_t p_vout );
#endif
/* Video output */
int vout_SDLCreate ( vout_thread_t *p_vout, char *psz_display,
......@@ -61,19 +75,17 @@ int vout_SDLManage ( p_vout_thread_t p_vout );
void vout_SDLDisplay ( p_vout_thread_t p_vout );
void vout_SDLSetPalette ( p_vout_thread_t p_vout,
u16 *red, u16 *green, u16 *blue, u16 *transp );
#if 0
/* YUV transformations */
int yuv_CInit ( p_vout_thread_t p_vout );
int yuv_CReset ( p_vout_thread_t p_vout );
void yuv_CEnd ( p_vout_thread_t p_vout );
#endif
/* Interface */
int intf_SDLCreate ( p_intf_thread_t p_intf );
void intf_SDLDestroy ( p_intf_thread_t p_intf );
void intf_SDLManage ( p_intf_thread_t p_intf );
/*****************************************************************************
* * Capabilities defined in the other files.
******************************************************************************/
extern void aout_getfunctions( function_list_t * p_function_list );
/*****************************************************************************
* GetConfig: get the plugin structure and configuration
*****************************************************************************/
......@@ -88,17 +100,7 @@ plugin_info_t * GetConfig( void )
p_info->aout_GetPlugin = NULL;
p_info->vout_GetPlugin = vout_GetPlugin;
p_info->intf_GetPlugin = intf_GetPlugin;
/* TODO: before doing this, we have to know if the videoCard is capable of
* hardware YUV -> display acceleration....
*/
#if 0
p_info->yuv_GetPlugin = (void *) yuv_GetPlugin;
#else
p_info->yuv_GetPlugin = NULL;
#endif
/* if the SDL libraries are there, assume we can enter the
......@@ -138,12 +140,64 @@ static void intf_GetPlugin( p_intf_thread_t p_intf )
p_intf->p_sys_manage = intf_SDLManage;
}
#if 0
static void yuv_GetPlugin( p_vout_thread_t p_vout )
/*****************************************************************************
* Audio stuff: All the new modules things
*****************************************************************************/
/*****************************************************************************
* InitModule: get the module structure and configuration.
*****************************************************************************
* We have to fill psz_name, psz_longname and psz_version. These variables
* will be strdup()ed later by the main application because the module can
* be unloaded later to save memory, and we want to be able to access this
* data even after the module has been unloaded.
*****************************************************************************/
int InitModule( module_t * p_module )
{
p_module->psz_name = MODULE_STRING;
p_module->psz_longname = "Linux SDL audio module";
p_module->psz_version = VERSION;
p_module->i_capabilities = MODULE_CAPABILITY_NULL
| MODULE_CAPABILITY_AOUT;
return( 0 );
}
/*****************************************************************************
* ActivateModule: set the module to an usable state.
*****************************************************************************
* This function fills the capability functions and the configuration
* structure. Once ActivateModule() has been called, the i_usage can
* be set to 0 and calls to NeedModule() be made to increment it. To unload
* the module, one has to wait until i_usage == 0 and call DeactivateModule().
*****************************************************************************/
int ActivateModule( module_t * p_module )
{
p_vout->p_yuv_init = yuv_CInit;
p_vout->p_yuv_reset = yuv_CReset;
p_vout->p_yuv_end = yuv_CEnd;
p_module->p_functions = malloc( sizeof( module_functions_t ) );
if( p_module->p_functions == NULL )
{
return( -1 );
}
aout_getfunctions( &p_module->p_functions->aout );
p_module->p_config = p_config;
return( 0 );
}
/*****************************************************************************
* DeactivateModule: make sure the module can be unloaded.
*****************************************************************************
* This function must only be called when i_usage == 0. If it successfully
* returns, i_usage can be set to -1 and the module unloaded. Be careful to
* lock usage_lock during the whole process.
*****************************************************************************/
int DeactivateModule( module_t * p_module )
{
free( p_module->p_functions );
return( 0 );
}
#endif
/*****************************************************************************
* video_yuv.c: YUV transformation functions
* Provides functions to perform the YUV conversion. The functions provided here
* are a complete and portable C implementation, and may be replaced in certain
* case by optimized functions.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include "defs.h"
#include <math.h> /* exp(), pow() */
#include <errno.h> /* ENOMEM */
#include <stdlib.h> /* free() */
#include <string.h> /* strerror() */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
#include "plugins.h"
#include "video.h"
#include "video_output.h"
#include "video_yuv.h"
#include "intf_msg.h"
/*****************************************************************************
* vout_InitYUV: allocate and initialize translations tables
*****************************************************************************
* This function will allocate memory to store translation tables, depending
* of the screen depth.
*****************************************************************************/
int yuv_CInit( vout_thread_t *p_vout )
{
/* Initialize tables */
SetSDLYUV( p_vout );
return( 0 );
}
/*****************************************************************************
* yuv_CEnd: destroy translations tables
*****************************************************************************
* Free memory allocated by yuv_CCreate.
*****************************************************************************/
void yuv_CEnd( vout_thread_t *p_vout )
{
free( p_vout->yuv.p_base );
free( p_vout->yuv.p_buffer );
free( p_vout->yuv.p_offset );
}
/*****************************************************************************
* yuv_CReset: re-initialize translations tables
*****************************************************************************
* This function will initialize the tables allocated by vout_CreateTables and
* set functions pointers.
*****************************************************************************/
int yuv_CReset( vout_thread_t *p_vout )
{
yuv_CEnd( p_vout );
return( yuv_CInit( p_vout ) );
}
/* following functions are local */
/*****************************************************************************
* SetYUV: compute tables and set function pointers
+ *****************************************************************************/
void SetSDLYUV( vout_thread_t *p_vout )
{
/*
* Set functions pointers
*/
if( p_vout->b_grayscale )
{
/* Grayscale */
switch( p_vout->i_bytes_per_pixel )
{
case 1:
p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) Convert8;
p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) Convert8;
p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) Convert8;
break;
case 2:
p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) Convert16;
p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) Convert16;
p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) Convert16;
break;
case 3:
p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) Convert24;
p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) Convert24;
p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) Convert24;
break;
case 4:
p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) Convert32;
p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) Convert32;
p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) Convert32;
break;
}
}
else
{
/* Color */
switch( p_vout->i_bytes_per_pixel )
{
case 1:
p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertRGB8;
p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertRGB8;
p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertRGB8;
break;
case 2:
p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertRGB16;
p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertRGB16;
p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertRGB16;
break;
case 3:
p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertRGB24;
p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertRGB24;
p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertRGB24;
break;
case 4:
p_vout->yuv.p_Convert420 = (vout_yuv_convert_t *) ConvertRGB32;
p_vout->yuv.p_Convert422 = (vout_yuv_convert_t *) ConvertRGB32;
p_vout->yuv.p_Convert444 = (vout_yuv_convert_t *) ConvertRGB32;
break;
}
}
}