Commit 123b3214 authored by Christophe Massiot's avatar Christophe Massiot

Audio output 3. Expect major breakages.

parent cd7a6631
......@@ -22,7 +22,7 @@ INTERFACE := interface intf_eject
PLAYLIST := playlist
INPUT := input input_ext-plugins input_ext-dec input_ext-intf input_dec input_programs input_clock input_info
VIDEO_OUTPUT := video_output video_text vout_pictures vout_subpictures
AUDIO_OUTPUT := audio_output aout_ext-dec aout_pcm aout_spdif
AUDIO_OUTPUT := audio_output filters input mixer output
MISC := mtime modules threads cpu configuration netutils iso_lang messages objects extras
LIBVLC_OBJ := $(LIBVLC:%=src/%.o) \
......
#! /bin/sh
## bootstrap.sh file for vlc, the VideoLAN Client
## $Id: bootstrap.sh,v 1.9 2002/08/07 00:29:36 sam Exp $
## $Id: bootstrap.sh,v 1.10 2002/08/07 21:36:55 massiot Exp $
##
## Authors: Samuel Hocevar <sam@zoy.org>
......@@ -73,7 +73,7 @@ echo "$file."
echo -n " + fixing glade bugs: "
for file in gnome_interface.c gtk_interface.c
do
if grep -q "DO NOT EDIT THIS FILE" modules/gui/gtk/$file
if grep "DO NOT EDIT THIS FILE" modules/gui/gtk/$file 2>&1 > /dev/null
then
rm -f /tmp/$$.$file.bak
cat > /tmp/$$.$file.bak << EOF
......@@ -97,7 +97,7 @@ echo -n "$file "
done
file=gtk_support.h
if grep -q "DO NOT EDIT THIS FILE" modules/gui/gtk/$file
if grep "DO NOT EDIT THIS FILE" modules/gui/gtk/$file 2>&1 > /dev/null
then
rm -f /tmp/$$.$file.bak
sed 's/DO NOT EDIT THIS FILE.*/This file was created automatically by glade and fixed by bootstrap.sh/ ; s/#if.*ENABLE_NLS.*/#if defined( ENABLE_NLS ) \&\& defined ( HAVE_GETTEXT )/' < modules/gui/gtk/$file > /tmp/$$.$file.bak
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -437,9 +437,12 @@ BUILTINS="${BUILTINS}"
PLUGINS="${PLUGINS} misc/dummy/dummy misc/null/null"
PLUGINS="${PLUGINS} control/rc/rc misc/logger/logger access/file access/udp access/http misc/network/ipv4 misc/memcpy/memcpy"
PLUGINS="${PLUGINS} demux/mpeg/es demux/mpeg/audio demux/mpeg/mpeg_system demux/mpeg/ps demux/mpeg/ts"
PLUGINS="${PLUGINS} codec/mpeg_video/idct/idct codec/mpeg_video/idct/idctclassic codec/mpeg_video/motion/motion codec/a52old/imdct/imdct codec/a52old/downmix/downmix codec/mpeg_audio/mpeg_audio codec/a52old/a52old codec/mpeg_video/mpeg_video codec/lpcm/lpcm codec/spdif/spdif codec/spudec/spudec"
PLUGINS="${PLUGINS} codec/mpeg_video/idct/idct codec/mpeg_video/idct/idctclassic codec/mpeg_video/motion/motion codec/mpeg_video/mpeg_video codec/spudec/spudec"
#PLUGINS="${PLUGINS} codec/a52old/imdct/imdct codec/a52old/downmix/downmix codec/mpeg_audio/mpeg_audio codec/a52old/a52old codec/lpcm/lpcm codec/spdif/spdif"
PLUGINS="${PLUGINS} video_filter/deinterlace/deinterlace video_filter/invert video_filter/wall video_filter/transform video_filter/distort video_filter/clone video_filter/crop"
PLUGINS="${PLUGINS} visualization/scope/scope"
PLUGINS="${PLUGINS} audio_mixer/trivial"
PLUGINS="${PLUGINS} audio_output/file"
#PLUGINS="${PLUGINS} visualization/scope/scope"
PLUGINS="${PLUGINS} video_chroma/i420_rgb video_chroma/i420_yuy2 video_chroma/i422_yuy2 video_chroma/i420_ymga"
dnl
......@@ -808,7 +811,7 @@ then
fi
;;
xno)
dnl Compile without dvbpsi (dlopen version, works only under Linux)
dnl Compile without dvbpsi
;;
*)
AC_MSG_CHECKING(for dvbpsi headers in ${with_dvbpsi})
......@@ -963,7 +966,7 @@ then
mad_LDFLAGS="${mad_LDFLAGS} -L${real_mad_tree}/libmad/.libs"
LDFLAGS="${save_LDFLAGS} ${mad_LDFLAGS}"
AC_CHECK_LIB(mad, mad_bit_init, [
BUILTINS="${BUILTINS} codec/mad/mad"
#BUILTINS="${BUILTINS} codec/mad/mad"
mad_LDFLAGS="${mad_LDFLAGS} -lmad"
],[ AC_MSG_ERROR([the specified tree hasn't been compiled ])
],[])
......@@ -978,7 +981,7 @@ then
AC_CHECK_HEADERS(mad.h, ,
[ AC_MSG_ERROR([Cannot find development headers for libmad...]) ])
AC_CHECK_LIB(mad, mad_bit_init, [
PLUGINS="${PLUGINS} codec/mad/mad"
#PLUGINS="${PLUGINS} codec/mad/mad"
mad_LDFLAGS="${mad_LDFLAGS} -lmad" ],
[ AC_MSG_ERROR([Cannot find libmad library...]) ])
CFLAGS="${save_CFLAGS}"
......@@ -1067,9 +1070,11 @@ dnl
dnl a52 AC3 decoder plugin
dnl
AC_ARG_ENABLE(a52,
[ --enable-a52 AC3 support with liba52 (default enabled)])
[ --enable-a52 A/52 support with liba52 (default enabled)])
if test "x${enable_a52}" != "xno"
then
AC_ARG_WITH(a52,
[ --with-a52=PATH a52 headers and libraries])
AC_ARG_WITH(a52-tree,
[ --with-a52-tree=PATH a52dec tree for static linking ],[],[])
if test "x${with_a52_tree}" != "xno" -a "x${with_a52_tree}" != "x"
......@@ -1106,14 +1111,33 @@ then
AC_MSG_RESULT(no)
AC_MSG_ERROR([the specified tree doesn't have a52.h])
fi
else dnl no with args
else
if test "x${with_a52}" = "x"
then
test_LDFLAGS=""
test_CFLAGS=""
else
test_LDFLAGS="-L${with_a52}/lib"
test_CFLAGS="-I${with_a52}/include"
fi
save_CPPFLAGS="${CPPFLAGS}"
save_LDFLAGS="${LDFLAGS}"
CPPFLAGS="${save_CPPFLAGS} ${test_CFLAGS}"
LDFLAGS="${save_LDFLAGS} ${test_LDFLAGS}"
AC_CHECK_HEADERS(a52dec/a52.h, [
AC_CHECK_LIB(a52, a52_free, [
BUILTINS="${BUILTINS} codec/a52/a52"
a52_LDFLAGS="${a52_LDFLAGS} -la52 -lm"
a52_CFLAGS="${a52_CFLAGS}"
],[],[-lm])
a52_LDFLAGS="${a52_LDFLAGS} ${test_LDFLAGS} -la52 -lm"
a52_CFLAGS="${a52_CFLAGS} ${test_CFLAGS}"
],[
if test "x${enable_dvbpsi}" != "x"
then
AC_MSG_ERROR([Could not find a52 on your system: you may get it from http://liba52.sf.net])
fi
],[-lm])
])
CPPFLAGS="${save_CPPFLAGS}"
LDFLAGS="${save_LDFLAGS}"
fi
fi
......@@ -1377,14 +1401,14 @@ AC_ARG_WITH(,[Audio plugins:])
dnl
dnl OSS /dev/dsp module (enabled by default except on win32)
dnl
AC_ARG_ENABLE(dsp,
[ --enable-dsp Linux /dev/dsp support (enabled on Linux)])
AC_ARG_ENABLE(oss,
[ --enable-oss Linux OSS /dev/dsp support (enabled on Linux)])
if test "x${enable_dsp}" != "xno" &&
(test "x${SYS}" != "xmingw32" || test "x${enable_dsp}" = "xyes")
if test "x${enable_oss}" != "xno" &&
(test "x${SYS}" != "xmingw32" || test "x${enable_oss}" = "xyes")
then
AC_CHECK_HEADERS(soundcard.h sys/soundcard.h machine/soundcard.h, [
PLUGINS="${PLUGINS} audio_output/dsp/dsp"
#PLUGINS="${PLUGINS} audio_output/oss"
AC_CHECK_LIB(ossaudio,main,dsp_LDFLAGS="${dsp_LDFLAGS} -lossaudio")
])
fi
......@@ -1399,7 +1423,7 @@ AC_ARG_ENABLE(esd,
AC_PATH_PROG(ESD_CONFIG, esd-config, no)
if test "x${ESD_CONFIG}" != "xno"
then
PLUGINS="${PLUGINS} audio_output/esd/esd"
#PLUGINS="${PLUGINS} audio_output/esd"
esd_CFLAGS="${esd_CFLAGS} `${ESD_CONFIG} --cflags`"
esd_LDFLAGS="${esd_LDFLAGS} `${ESD_CONFIG} --libs`"
fi
......@@ -1415,7 +1439,7 @@ AC_ARG_ENABLE(arts,
AC_PATH_PROG(ARTS_CONFIG, artsc-config, no)
if test "x${ARTS_CONFIG}" != "xno"
then
PLUGINS="${PLUGINS} audio_output/arts/arts"
#PLUGINS="${PLUGINS} audio_output/arts"
arts_CFLAGS="${arts_CFLAGS} `${ARTS_CONFIG} --cflags`"
arts_LDFLAGS="${arts_LDFLAGS} `${ARTS_CONFIG} --libs `"
fi
......@@ -1431,7 +1455,7 @@ AC_ARG_ENABLE(alsa,
AC_CHECK_HEADER(alsa/asoundlib.h, AC_CHECK_LIB(asound, main, have_alsa="true", have_alsa="false"),have_alsa="false")
if test "x${have_alsa}" = "xtrue"
then
PLUGINS="${PLUGINS} audio_output/alsa/alsa"
#PLUGINS="${PLUGINS} audio_output/alsa"
alsa_LDFLAGS="${alsa_LDFLAGS} -lasound -lm -ldl"
fi
fi])
......@@ -1443,7 +1467,7 @@ AC_ARG_ENABLE(waveout,
[ --enable-waveout Win32 waveOut module (default enabled on Win32)])
if test "x${enable_waveout}" != "xno" -a "x${SYS}" = "xmingw32"
then
PLUGINS="${PLUGINS} audio_output/waveout/waveout"
#PLUGINS="${PLUGINS} audio_output/waveout"
waveout_LDFLAGS="-lwinmm"
fi
......
/*****************************************************************************
* aout_internal.h : internal defines for audio output
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: aout_internal.h,v 1.1 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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.
*****************************************************************************/
/*****************************************************************************
* aout_alloc_t : allocation of memory in the audio output
*****************************************************************************/
typedef struct aout_alloc_t
{
int i_alloc_type;
int i_bytes_per_sec; /* -1 if only the alloc_type is
* relevant. */
} aout_alloc_t;
#define AOUT_ALLOC_NONE 0
#define AOUT_ALLOC_STACK 1
#define AOUT_ALLOC_HEAP 2
#define aout_BufferAlloc( p_alloc, i_nb_usec, p_previous_buffer, p_new_buffer ) \
if ( (p_alloc)->i_alloc_type == AOUT_ALLOC_NONE ) \
{ \
(p_new_buffer) = p_previous_buffer; \
} \
else \
{ \
if ( (p_alloc)->i_alloc_type == AOUT_ALLOC_STACK ) \
{ \
(p_new_buffer) = alloca( (u64)(p_alloc)->i_bytes_per_sec \
* i_nb_usec \
/ 1000000 + 1 + sizeof(aout_buffer_t) ); \
} \
else \
{ \
(p_new_buffer) = malloc( (u64)(p_alloc)->i_bytes_per_sec \
* i_nb_usec \
/ 1000000 + 1 + sizeof(aout_buffer_t) ); \
} \
(p_new_buffer)->i_alloc_type = (p_alloc)->i_alloc_type; \
(p_new_buffer)->i_size = (u64)(p_alloc)->i_bytes_per_sec \
* i_nb_usec / 1000000 + 1; \
(p_new_buffer)->p_buffer = (void *)(p_new_buffer) \
+ sizeof(aout_buffer_t); \
if ( (p_previous_buffer) != NULL ) \
{ \
(p_new_buffer)->start_date = \
((aout_buffer_t *)p_previous_buffer)->start_date; \
(p_new_buffer)->end_date = \
((aout_buffer_t *)p_previous_buffer)->end_date; \
} \
}
#define aout_BufferFree( p_buffer ) \
if ( (p_buffer)->i_alloc_type == AOUT_ALLOC_HEAP ) \
{ \
free( p_buffer ); \
}
/*****************************************************************************
* aout_fifo_t : audio output buffer FIFO
*****************************************************************************/
typedef struct aout_fifo_t
{
vlc_mutex_t lock;
struct aout_buffer_t * p_first;
struct aout_buffer_t ** pp_last;
} aout_fifo_t;
static inline void aout_FifoInit( struct aout_instance_t * p_aout,
aout_fifo_t * p_fifo )
{
vlc_mutex_init( (vlc_object_t *)p_aout, &p_fifo->lock );
p_fifo->p_first = NULL;
p_fifo->pp_last = &p_fifo->p_first;
}
static inline void aout_FifoPush( struct aout_instance_t * p_aout,
aout_fifo_t * p_fifo,
aout_buffer_t * p_buffer )
{
vlc_mutex_lock( &p_fifo->lock );
*p_fifo->pp_last = p_buffer;
p_fifo->pp_last = &p_buffer->p_next;
*p_fifo->pp_last = NULL;
vlc_mutex_unlock( &p_fifo->lock );
}
/* This function supposes there is one buffer in p_fifo. */
static inline aout_buffer_t * aout_FifoPop( struct aout_instance_t * p_aout,
aout_fifo_t * p_fifo )
{
aout_buffer_t * p_buffer;
vlc_mutex_lock( &p_fifo->lock );
p_buffer = p_fifo->p_first;
p_fifo->p_first = p_buffer->p_next;
if ( p_fifo->p_first == NULL )
{
p_fifo->pp_last = &p_fifo->p_first;
}
vlc_mutex_unlock( &p_fifo->lock );
return p_buffer;
}
static inline void aout_FifoDestroy( struct aout_instance_t * p_aout,
aout_fifo_t * p_fifo )
{
aout_buffer_t * p_buffer;
vlc_mutex_destroy( &p_fifo->lock );
p_buffer = p_fifo->p_first;
while ( p_buffer != NULL )
{
aout_buffer_t * p_next = p_buffer->p_next;
aout_BufferFree( p_buffer );
p_buffer = p_next;
}
}
/*****************************************************************************
* aout_filter_t : audio output filter
*****************************************************************************/
typedef struct aout_filter_t
{
VLC_COMMON_MEMBERS
audio_sample_format_t input;
audio_sample_format_t output;
aout_alloc_t output_alloc;
module_t * p_module;
struct aout_filter_sys_t * p_sys;
void (* pf_do_work)( struct aout_instance_t *,
struct aout_filter_t *,
struct aout_buffer_t *,
struct aout_buffer_t * );
vlc_bool_t b_in_place;
} aout_filter_t;
/*****************************************************************************
* aout_mixer_t : audio output mixer
*****************************************************************************/
typedef struct aout_mixer_t
{
audio_sample_format_t input;
audio_sample_format_t output;
aout_alloc_t output_alloc;
module_t * p_module;
struct aout_mixer_sys_t * p_sys;
void (* pf_do_work)( struct aout_instance_t *,
struct aout_buffer_t * );
} aout_mixer_t;
/*****************************************************************************
* aout_input_t : input stream for the audio output
*****************************************************************************/
struct aout_input_t
{
audio_sample_format_t input;
aout_alloc_t input_alloc;
/* pre-filters */
aout_filter_t * pp_filters[AOUT_MAX_FILTERS];
int i_nb_filters;
aout_fifo_t fifo;
char * p_first_byte_to_mix;
};
/*****************************************************************************
* aout_output_t : output stream for the audio output
*****************************************************************************/
typedef struct aout_output_t
{
audio_sample_format_t output;
/* post-filters */
aout_filter_t * pp_filters[AOUT_MAX_FILTERS];
int i_nb_filters;
aout_fifo_t fifo;
mtime_t last_date;
struct module_t * p_module;
struct aout_sys_t * p_sys;
int (* pf_setformat)( aout_instance_t * );
void (* pf_play)( aout_instance_t *, aout_buffer_t * );
int i_nb_samples;
} aout_output_t;
/*****************************************************************************
* aout_instance_t : audio output thread descriptor
*****************************************************************************/
struct aout_instance_t
{
VLC_COMMON_MEMBERS
/* Input streams & pre-filters */
vlc_mutex_t input_lock;
vlc_cond_t input_signal;
int i_inputs_active;
vlc_bool_t b_change_requested;
aout_input_t * pp_inputs[AOUT_MAX_INPUTS];
int i_nb_inputs;
/* Mixer */
vlc_mutex_t mixer_lock;
vlc_cond_t mixer_signal;
vlc_bool_t b_mixer_active;
aout_mixer_t mixer;
/* Output plug-in */
aout_output_t output;
};
/*****************************************************************************
* Prototypes
*****************************************************************************/
void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer );
int aout_FiltersCreatePipeline( aout_instance_t * p_aout,
aout_filter_t ** pp_filters,
int * pi_nb_filters,
audio_sample_format_t * p_input_format,
audio_sample_format_t * p_output_format );
void aout_FiltersDestroyPipeline( aout_instance_t * p_aout,
aout_filter_t ** pp_filters,
int i_nb_filters );
void aout_FiltersHintBuffers( aout_instance_t * p_aout,
aout_filter_t ** pp_filters,
int i_nb_filters, aout_alloc_t * p_first_alloc );
void aout_FiltersPlay( aout_instance_t * p_aout,
aout_filter_t ** pp_filters,
int i_nb_filters, aout_buffer_t ** pp_input_buffer );
int aout_MixerNew( aout_instance_t * p_aout );
void aout_MixerDelete( aout_instance_t * p_aout );
void aout_MixerRun( aout_instance_t * p_aout );
int aout_OutputNew( aout_instance_t * p_aout,
audio_sample_format_t * p_format );
void aout_OutputPlay( aout_instance_t * p_aout, aout_buffer_t * p_buffer );
void aout_OutputDelete( aout_instance_t * p_aout );
int aout_FormatToBytes( audio_sample_format_t * p_format );
/*****************************************************************************
* audio_output.h : audio output thread interface
* audio_output.h : audio output interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: audio_output.h,v 1.51 2002/08/04 17:23:41 sam Exp $
* Copyright (C) 2002 VideoLAN
* $Id: audio_output.h,v 1.52 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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
......@@ -23,168 +22,74 @@
*****************************************************************************/
/*****************************************************************************
* aout_increment_t
* audio_sample_format_t
*****************************************************************************
* This structure is used to keep the progression of an index up-to-date, in
* order to avoid rounding problems and heavy computations, as the function
* that handles this structure only uses additions.
* This structure defines a format for audio samples.
*****************************************************************************/
typedef struct aout_increment_t
struct audio_sample_format_t
{
/* The remainder is used to keep track of the fractional part of the
* index. */
int i_r;
/*
* The increment structure is initialized with the result of an euclidean
* division :
*
* i_x i_b
* ----- = i_a + -----
* i_y i_c
*
*/
int i_a, i_b, i_c;
} aout_increment_t;
/*****************************************************************************
* aout_fifo_t
*****************************************************************************/
struct aout_fifo_t
{
/* See the fifo formats below */
int i_format;
int i_channels;
int i_rate;
int i_frame_size;
vlc_bool_t b_die;
int i_fifo; /* Just to keep track of the fifo index */
vlc_mutex_t data_lock;
vlc_cond_t data_wait;
u8 * buffer;
mtime_t * date;
/* The start frame is the first frame in the buffer that contains decoded
* audio data. It it also the first frame in the current timestamped frame
* area, ie the first dated frame in the decoded part of the buffer. :-p */
int i_start_frame;
vlc_bool_t b_start_frame;
/* The next frame is the end frame of the current timestamped frame area,
* ie the first dated frame after the start frame. */
int i_next_frame;
vlc_bool_t b_next_frame;
/* The end frame is the first frame, after the start frame, that doesn't
* contain decoded audio data. That's why the end frame is the first frame
* where the audio decoder can store its decoded audio frames. */
int i_end_frame;
/* Current index in p_aout->buffer */
int i_unit;
/* Max index in p_aout->buffer */
int i_unit_limit;
/* Structure used to calculate i_unit with a Bresenham algorithm */
aout_increment_t unit_increment;
/* The following variable is used to store the number of remaining audio
* units in the current timestamped frame area. */
int i_units;
};
#define AOUT_FIFO_ISEMPTY( fifo ) \
( (fifo).i_end_frame == (fifo).i_start_frame )
#define AOUT_FIFO_ISFULL( fifo ) \
( ((((fifo).i_end_frame + 1) - (fifo).i_start_frame) & AOUT_FIFO_SIZE) == 0 )
#define AOUT_FIFO_INC( i_index ) \
( ((i_index) + 1) & AOUT_FIFO_SIZE )
/* List of known fifo formats */
#define AOUT_FIFO_NONE 0
#define AOUT_FIFO_PCM 1
#define AOUT_FIFO_SPDIF 2
/*****************************************************************************
* aout_thread_t : audio output thread descriptor
*****************************************************************************/
struct aout_thread_t
{
VLC_COMMON_MEMBERS
vlc_mutex_t fifos_lock;
aout_fifo_t fifo[ AOUT_MAX_FIFOS ];
/* Plugin used and shortcuts to access its capabilities */
module_t * p_module;
int ( *pf_setformat ) ( aout_thread_t * );
int ( *pf_getbufinfo ) ( aout_thread_t * , int );
void ( *pf_play ) ( aout_thread_t * , byte_t *, int );
void * buffer;
/* The s32 buffer is used to mix all the audio fifos together before
* converting them and storing them in the audio output buffer */
s32 * s32_buffer;
/* The size of the audio output buffer is kept in audio units, as this is
* the only unit that is common with every audio decoder and audio fifo */
int i_units;
/* date is the moment where the first audio unit of the output buffer
* will be played */
mtime_t date;
/* The current volume */
int i_volume;
int i_savedvolume;
/* Format of the audio output samples, number of channels, and
* rate and gain (in Hz) of the audio output sound */
int i_format;
int i_channels;
int i_rate;
/* Latency of the audio output plugin, in bytes */
int i_latency;
/* there might be some useful private structure, such as audio_buf_info
* for the OSS output */
aout_sys_t * p_sys;
};
/* Those are from <linux/soundcard.h> but are needed because of formats
* on other platforms */
#define AOUT_FMT_MU_LAW 0x00000001
#define AOUT_FMT_A_LAW 0x00000002
#define AOUT_FMT_IMA_ADPCM 0x00000004
#define AOUT_FMT_U8 0x00000008
#define AOUT_FMT_S16_LE 0x00000010 /* Little endian signed 16 */
#define AOUT_FMT_S16_BE 0x00000020 /* Big endian signed 16 */
#define AOUT_FMT_S8 0x00000040
#define AOUT_FMT_U16_LE 0x00000080 /* Little endian U16 */
#define AOUT_FMT_U16_BE 0x00000100 /* Big endian U16 */
#define AOUT_FMT_A52 0x00000400 /* Dolby Digital A52 */
#define AOUT_FMT_A52 0x00000400 /* ATSC A/52 (for SP/DIF) */
#define AOUT_FMT_FLOAT32 0x00000800
#define AOUT_FMT_FIXED32 0x00001000
#define AOUT_FMTS_IDENTICAL( p_first, p_second ) ( \
(p_first->i_format == p_second->i_format) \
&& (p_first->i_rate == p_second->i_rate) \
&& (p_first->i_channels == p_second->i_channels \
|| p_first->i_channels == -1 || p_second->i_channels == -1) )
#ifdef WORDS_BIGENDIAN
#define AOUT_FMT_S16_NE AOUT_FMT_S16_BE
# define AOUT_FMT_S16_NE AOUT_FMT_S16_BE
# define AOUT_FMT_U16_NE AOUT_FMT_U16_BE
#else
#define AOUT_FMT_S16_NE AOUT_FMT_S16_LE
# define AOUT_FMT_S16_NE AOUT_FMT_S16_LE
# define AOUT_FMT_U16_NE AOUT_FMT_U16_LE
#endif
/* Number of samples in an A52 frame */
#define A52_FRAME_SIZE 1536
/*****************************************************************************
* aout_buffer_t : audio output buffer
*****************************************************************************/
struct aout_buffer_t
{
char * p_buffer;
int i_alloc_type;
size_t i_size;
int i_nb_samples;
mtime_t start_date, end_date;
/* Size of a frame for spdif output */
#define SPDIF_FRAME_SIZE 6144
struct aout_buffer_t * p_next;
};
/*****************************************************************************
* Prototypes
*****************************************************************************/
aout_thread_t * aout_CreateThread ( vlc_object_t *, int, int );
void aout_DestroyThread ( aout_thread_t * );
#define aout_CreateFifo(a,b,c,d,e,f) __aout_CreateFifo(VLC_OBJECT(a),b,c,d,e,f)
VLC_EXPORT( aout_fifo_t *, __aout_CreateFifo, ( vlc_object_t *, int, int, int, int, void * ) );
VLC_EXPORT( void, aout_DestroyFifo, ( aout_fifo_t *p_fifo ) );
void aout_FreeFifo ( aout_fifo_t *p_fifo );
/* From audio_output.c : */
#define aout_NewInstance(a) __aout_NewInstance(VLC_OBJECT(a))
VLC_EXPORT( aout_instance_t *, __aout_NewInstance, ( vlc_object_t * ) );
VLC_EXPORT( void, aout_DeleteInstance, ( aout_instance_t * ) );
VLC_EXPORT( aout_buffer_t *, aout_BufferNew, ( aout_instance_t *, aout_input_t *, size_t ) );
VLC_EXPORT( void, aout_BufferDelete, ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) );
VLC_EXPORT( void, aout_BufferPlay, ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) );
/* From input.c : */
#define aout_InputNew(a,b,c) __aout_InputNew(VLC_OBJECT(a),b,c)
VLC_EXPORT( aout_input_t *, __aout_InputNew, ( vlc_object_t *, aout_instance_t **, audio_sample_format_t * ) );
VLC_EXPORT( void, aout_InputDelete, ( aout_instance_t *, aout_input_t * ) );
/* From output.c : */
VLC_EXPORT( aout_buffer_t *, aout_OutputNextBuffer, ( aout_instance_t *, mtime_t ) );
......@@ -129,22 +129,11 @@
#define VOLUME_MAX 1024
#define VOLUME_MIN 0
/* Number of audio output frames contained in an audio output fifo.
* (AOUT_FIFO_SIZE + 1) must be a power of 2, in order to optimise the
* %(AOUT_FIFO_SIZE + 1) operation with an &AOUT_FIFO_SIZE.
* With 255 we have at least 255*384/2/48000=1 second of sound */
#define AOUT_FIFO_SIZE 255
/* Maximum number of audio fifos. The value of AOUT_MAX_FIFOS should be a power
* of two, in order to optimize the '/AOUT_MAX_FIFOS' and '*AOUT_MAX_FIFOS'
* operations with '>>' and '<<' (gcc changes this at compilation-time) */
#define AOUT_MAX_FIFOS 2
/* Duration (in microseconds) of an audio output buffer should be :
* - short, in order to be able to play a new song very quickly (especially a
* song from the interface)
* - long, in order to perform the buffer calculations as few as possible */
#define AOUT_BUFFER_DURATION 90000
/* Max number of pre-filters per input, and max-number of post-filters */
#define AOUT_MAX_FILTERS 10
/* Max number of inputs */
#define AOUT_MAX_INPUTS 5
/*****************************************************************************
* Video configuration
......
/* include/defs.h.in. Generated automatically from configure.in by autoheader 2.13. */
/* include/defs.h.in. Generated from configure.in by autoheader. */
/* Define if using alloca.c. */
#undef C_ALLOCA
/* Maximum supported data alignment */
#undef ATTRIBUTE_ALIGNED_MAX
/* Define to empty if the keyword does not work. */
#undef const
/* Define if $CC groks 3D Now! inline assembly. */
#undef CAN_COMPILE_3DNOW
/* Define if $CC groks AltiVec inline assembly. */
#undef CAN_COMPILE_ALTIVEC
/* Define if your compiler groks C AltiVec extensions. */
#undef CAN_COMPILE_C_ALTIVEC
/* Define if $CC groks SSE inline assembly. */
#undef CAN_COMPILE_SSE
/* The ./configure command line */
#undef CONFIGURE_LINE
/* Copyright string */
#undef COPYRIGHT_MESSAGE
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
This function is required for alloca.c support on those systems. */
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
#undef CRAY_STACKSEG_END
/* Define if you have alloca, as a function or macro. */
/* Define to 1 if using `alloca.c'. */
#undef C_ALLOCA
/* Define if <X11/extensions/dpms.h> defines DPMSInfo. */
#undef DPMSINFO_IN_DPMS_H
/* Define to 1 if translation of program messages to the user's native
language is requested. */
#undef ENABLE_NLS
/* Define to 1 if you have the <a52dec/a52.h> header file. */
#undef HAVE_A52DEC_A52_H
/* Define to 1 if you have `alloca', as a function or macro. */
#undef HAVE_ALLOCA
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
#undef HAVE_ALLOCA_H
/* Define if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define to 1 if you have the <argz.h> header file. */
#undef HAVE_ARGZ_H
/* Define as __inline if that's what the C compiler calls it. */
#undef inline
/* Define to 1 if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to `long' if <sys/types.h> doesn't define. */
#undef off_t
/* Define to 1 if you have the `atoll' function. */
#undef HAVE_ATOLL
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define to 1 if you have the <Cocoa/Cocoa.h> header file. */
#undef HAVE_COCOA_COCOA_H
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* Define to 1 if you have the <cthreads.h> header file. */
#undef HAVE_CTHREADS_H
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown
*/
#undef STACK_DIRECTION
/* Define to 1 if you have the `dcgettext' function. */
#undef HAVE_DCGETTEXT
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define to 1 if you have the <ddraw.h> header file. */
#undef HAVE_DDRAW_H
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define if <time.h> defines nanosleep. */
#undef HAVE_DECL_NANOSLEEP
/* Define if you have the __argz_count function. */
#undef HAVE___ARGZ_COUNT
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define if you have the __argz_next function. */
#undef HAVE___ARGZ_NEXT
/* Define to 1 if you have the <dvbpsi/dr.h> header file. */
#undef HAVE_DVBPSI_DR_H
/* Define if you have the __argz_stringify function. */
#undef HAVE___ARGZ_STRINGIFY
/* Define to 1 if you have the <dvdcss/dvdcss.h> header file. */
#undef HAVE_DVDCSS_DVDCSS_H
/* Define if you have the atoll function. */
#undef HAVE_ATOLL
/* Define to 1 if you have the <dvdplay/dvdplay.h> header file. */
#undef HAVE_DVDPLAY_DVDPLAY_H
/* Define if you have the dcgettext function. */
#undef HAVE_DCGETTEXT
/* Define to 1 if you have the <dvdread/dvd_reader.h> header file. */
#undef HAVE_DVDREAD_DVD_READER_H
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the feof_unlocked function. */
/* Define to 1 if you have the `feof_unlocked' function. */
#undef HAVE_FEOF_UNLOCKED
/* Define if you have the fgets_unlocked function. */
/* Define to 1 if you have the `fgets_unlocked' function. */
#undef HAVE_FGETS_UNLOCKED
/* Define if you have the getcwd function. */
/* Define to 1 if you have the <gdk/gdk.h> header file. */
#undef HAVE_GDK_GDK_H
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
/* Define if you have the getegid function. */
/* Define to 1 if you have the `getegid' function. */
#undef HAVE_GETEGID
/* Define if you have the geteuid function. */
/* Define to 1 if you have the `geteuid' function. */
#undef HAVE_GETEUID
/* Define if you have the getgid function. */
/* Define to 1 if you have the `getgid' function. */
#undef HAVE_GETGID
/* Define if you have the gethostbyname2 function. */
/* Define to 1 if you have the `gethostbyname2' function. */
#undef HAVE_GETHOSTBYNAME2
/* Define if you have the getpagesize function. */
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* getopt support */
#undef HAVE_GETOPT_LONG
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE
/* Define if you have the getpwuid function. */
/* Define to 1 if you have the `getpwuid' function. */
#undef HAVE_GETPWUID
/* Define if you have the gettimeofday function. */
/* Define if the GNU gettext() function is already present or preinstalled. */
#undef HAVE_GETTEXT
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the getuid function. */
/* Define to 1 if you have the `getuid' function. */
#undef HAVE_GETUID
/* Define if you have the isatty function. */
#undef HAVE_ISATTY
/* Define if you have the memalign function. */
#undef HAVE_MEMALIGN
/* Define if you have the mempcpy function. */
#undef HAVE_MEMPCPY
/* Define if you have the munmap function. */
#undef HAVE_MUNMAP
/* Define if you have the posix_memalign function. */
#undef HAVE_POSIX_MEMALIGN
/* Define if you have the putenv function. */
#undef HAVE_PUTENV
/* Define if you have the select function. */
#undef HAVE_SELECT
/* Define if you have the setenv function. */
#undef HAVE_SETENV
/* Define if you have the setlocale function. */
#undef HAVE_SETLOCALE
/* Define if you have the sigrelse function. */
#undef HAVE_SIGRELSE
/* Define to 1 if you have the <glib.h> header file. */
#undef HAVE_GLIB_H
/* Define if you have the stpcpy function. */
#undef HAVE_STPCPY
/* Define to 1 if you have the <gnome.h> header file. */
#undef HAVE_GNOME_H
/* Define if you have the strcasecmp function. */
#undef HAVE_STRCASECMP
/* Define to 1 if you have the <gtk/gtk.h> header file. */
#undef HAVE_GTK_GTK_H
/* Define if you have the strchr function. */
#undef HAVE_STRCHR
/* Define if you have the iconv() function. */
#undef HAVE_ICONV
/* Define if you have the strdup function. */
#undef HAVE_STRDUP
/* Define to 1 if you have the <image.h> header file. */
#undef HAVE_IMAGE_H
/* Define if you have the strerror function. */
#undef HAVE_STRERROR
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define if you have the strndup function. */
#undef HAVE_STRNDUP
/* For FreeBSD VCD support */
#undef HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H
/* Define if you have the strtod function. */
#undef HAVE_STRTOD
/* Define to 1 if you have the `isatty' function. */
#undef HAVE_ISATTY
/* Define if you have the strtol function. */
#undef HAVE_STRTOL
/* Define to 1 if you have the <kernel/OS.h> header file. */
#undef HAVE_KERNEL_OS_H
/* Define if you have the strtoul function. */
#undef HAVE_STRTOUL
/* Define to 1 if you have the <kernel/scheduler.h> header file. */
#undef HAVE_KERNEL_SCHEDULER_H
/* Define if you have the swab function. */
#undef HAVE_SWAB
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#undef HAVE_LANGINFO_CODESET
/* Define if you have the tsearch function. */
#undef HAVE_TSEARCH
/* Define if your <locale.h> file defines LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Define if you have the vasprintf function. */
#undef HAVE_VASPRINTF
/* Define to 1 if you have the <libdv/dv.h> header file. */
#undef HAVE_LIBDV_DV_H
/* Define if you have the <Cocoa/Cocoa.h> header file. */
#undef HAVE_COCOA_COCOA_H
/* Define to 1 if you have the `pth' library (-lpth). */
#undef HAVE_LIBPTH
/* Define if you have the <Ph.h> header file. */
#undef HAVE_PH_H
/* Define to 1 if you have the `st' library (-lst). */
#undef HAVE_LIBST
/* Define if you have the <X11/Xlib.h> header file. */
#undef HAVE_X11_XLIB_H
/* Define to 1 if you have the <libv4l/v4l.h> header file. */
#undef HAVE_LIBV4L_V4L_H
/* Define if you have the <X11/extensions/Xv.h> header file. */
#undef HAVE_X11_EXTENSIONS_XV_H
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define if you have the <X11/extensions/dpms.h> header file. */
#undef HAVE_X11_EXTENSIONS_DPMS_H
/* Define to 1 if you have the <linux/fb.h> header file. */
#undef HAVE_LINUX_FB_H
/* Define if you have the <a52dec/a52.h> header file. */
#undef HAVE_A52DEC_A52_H
/* Define to 1 if you have the <linux/version.h> header file. */
#undef HAVE_LINUX_VERSION_H
/* Define if you have the <argz.h> header file. */
#undef HAVE_ARGZ_H
/* Define to 1 if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define to 1 if you have the <machine/param.h> header file. */
#undef HAVE_MACHINE_PARAM_H
/* Define if you have the <cthreads.h> header file. */
#undef HAVE_CTHREADS_H
/* Define to 1 if you have the <machine/soundcard.h> header file. */
#undef HAVE_MACHINE_SOUNDCARD_H
/* Define if you have the <ddraw.h> header file. */
#undef HAVE_DDRAW_H
/* Define to 1 if you have the <mad.h> header file. */
#undef HAVE_MAD_H
/* Define if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
/* Define if you have the <dvbpsi/dr.h> header file. */
#undef HAVE_DVBPSI_DR_H
/* Define to 1 if you have the `memalign' function. */
#undef HAVE_MEMALIGN
/* Define if you have the <dvdcss/dvdcss.h> header file. */
#undef HAVE_DVDCSS_DVDCSS_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define if you have the <dvdplay/dvdplay.h> header file. */
#undef HAVE_DVDPLAY_DVDPLAY_H
/* Define to 1 if you have the `mempcpy' function. */
#undef HAVE_MEMPCPY
/* Define if you have the <dvdread/dvd_reader.h> header file. */
#undef HAVE_DVDREAD_DVD_READER_H
/* Define to 1 if you have a working `mmap' system call. */
#undef HAVE_MMAP
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the `munmap' function. */
#undef HAVE_MUNMAP
/* Define if you have the <gdk/gdk.h> header file. */
#undef HAVE_GDK_GDK_H
/* Define if nanosleep is available. */
#undef HAVE_NANOSLEEP
/* Define if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define if you have the <glib.h> header file. */
#undef HAVE_GLIB_H
/* Define to 1 if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H
/* Define if you have the <gnome.h> header file. */
#undef HAVE_GNOME_H
/* Define to 1 if you have the <nl_types.h> header file. */
#undef HAVE_NL_TYPES_H
/* Define if you have the <gtk/gtk.h> header file. */
#undef HAVE_GTK_GTK_H
/* Define to 1 if you have the <ogg/ogg.h> header file. */
#undef HAVE_OGG_OGG_H
/* Define if you have the <image.h> header file. */
#undef HAVE_IMAGE_H
/* Define to 1 if you have the <Ph.h> header file. */
#undef HAVE_PH_H
/* Define if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `posix_memalign' function. */
#undef HAVE_POSIX_MEMALIGN
/* Define if you have the <kernel/OS.h> header file. */
#undef HAVE_KERNEL_OS_H
/* Define to 1 if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
/* Define if you have the <kernel/scheduler.h> header file. */
#undef HAVE_KERNEL_SCHEDULER_H
/* Define to 1 if you have the `putenv' function. */
#undef HAVE_PUTENV
/* Define if you have the <libdv/dv.h> header file. */
#undef HAVE_LIBDV_DV_H
/* Define to 1 if you have the `select' function. */
#undef HAVE_SELECT
/* Define if you have the <libv4l/v4l.h> header file. */
#undef HAVE_LIBV4L_V4L_H
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
/* Define if you have the <linux/fb.h> header file. */
#undef HAVE_LINUX_FB_H
/* Define to 1 if you have the `sigrelse' function. */
#undef HAVE_SIGRELSE
/* Define if you have the <linux/version.h> header file. */
#undef HAVE_LINUX_VERSION_H
/* Define to 1 if you have the <soundcard.h> header file. */
#undef HAVE_SOUNDCARD_H
/* Define if you have the <locale.h> header file. */
#undef HAVE_LOCALE_H
/* Define to 1 if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define if you have the <machine/param.h> header file. */
#undef HAVE_MACHINE_PARAM_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define if you have the <machine/soundcard.h> header file. */
#undef HAVE_MACHINE_SOUNDCARD_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <mad.h> header file. */
#undef HAVE_MAD_H
/* Define to 1 if you have the `stpcpy' function. */
#undef HAVE_STPCPY
/* Define if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
/* Define to 1 if you have the `strcasecmp' function. */
#undef HAVE_STRCASECMP
/* Define if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H
/* Define to 1 if you have the `strchr' function. */
#undef HAVE_STRCHR
/* Define if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define to 1 if you have the `strdup' function. */
#undef HAVE_STRDUP
/* Define if you have the <nl_types.h> header file. */
#undef HAVE_NL_TYPES_H
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
/* Define if you have the <ogg/ogg.h> header file. */
#undef HAVE_OGG_OGG_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define if you have the <pthread.h> header file. */
#undef HAVE_PTHREAD_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if you have the <soundcard.h> header file. */
#undef HAVE_SOUNDCARD_H
/* Define to 1 if you have the `strndup' function. */
#undef HAVE_STRNDUP
/* Define if you have the <stddef.h> header file. */
#undef HAVE_STDDEF_H
/* Define to 1 if you have the `strtod' function. */
#undef HAVE_STRTOD
/* Define if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the `strtol' function. */
#undef HAVE_STRTOL
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `strtoul' function. */
#undef HAVE_STRTOUL
/* Define if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define if <sys/time.h> defines struct timespec. */
#undef HAVE_STRUCT_TIMESPEC
/* Define if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the `swab' function. */
#undef HAVE_SWAB
/* Define if you have the <sys/int_types.h> header file. */
/* Define to 1 if you have the <sys/int_types.h> header file. */
#undef HAVE_SYS_INT_TYPES_H
/* Define if you have the <sys/param.h> header file. */
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define if you have the <sys/shm.h> header file. */
/* Define to 1 if you have the <sys/shm.h> header file. */
#undef HAVE_SYS_SHM_H
/* Define if you have the <sys/socket.h> header file. */
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define if you have the <sys/sockio.h> header file. */
/* Define to 1 if you have the <sys/sockio.h> header file. */
#undef HAVE_SYS_SOCKIO_H
/* Define if you have the <sys/soundcard.h> header file. */
/* Define to 1 if you have the <sys/soundcard.h> header file. */
#undef HAVE_SYS_SOUNDCARD_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define if you have the <sys/times.h> header file. */
/* Define to 1 if you have the <sys/times.h> header file. */
#undef HAVE_SYS_TIMES_H
/* Define if you have the <sys/types.h> header file. */
/* Define to 1 if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define if you have the <unistd.h> header file. */
/* Define to 1 if you have the `tsearch' function. */
#undef HAVE_TSEARCH
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the pth library (-lpth). */
#undef HAVE_LIBPTH
/* Support for variadic macros */
#undef HAVE_VARIADIC_MACROS
/* Define if you have the st library (-lst). */
#undef HAVE_LIBST
/* Define to 1 if you have the `vasprintf' function. */
#undef HAVE_VASPRINTF
/* Package name */
#undef VLC_PACKAGE
/* Define to 1 if you have the <X11/extensions/dpms.h> header file. */
#undef HAVE_X11_EXTENSIONS_DPMS_H
/* Package version */
#undef VLC_VERSION
/* Define to 1 if you have the <X11/extensions/Xv.h> header file. */
#undef HAVE_X11_EXTENSIONS_XV_H
/* Define if you have the iconv() function. */
#undef HAVE_ICONV
/* Define to 1 if you have the <X11/Xlib.h> header file. */
#undef HAVE_X11_XLIB_H
/* Define to 1 if you have the `__argz_count' function. */
#undef HAVE___ARGZ_COUNT
/* Define to 1 if you have the `__argz_next' function. */
#undef HAVE___ARGZ_NEXT
/* Define to 1 if you have the `__argz_stringify' function. */
#undef HAVE___ARGZ_STRINGIFY
/* Define as const if the declaration of iconv() needs const. */
#undef ICONV_CONST
/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#undef HAVE_LANGINFO_CODESET
/* String suffix for module functions */
#undef MODULE_SUFFIX
/* Define if your <locale.h> file defines LC_MESSAGES. */
#undef HAVE_LC_MESSAGES
/* Symbol suffix for module functions */
#undef MODULE_SYMBOL
/* Define to 1 if translation of program messages to the user's native language
is requested. */
#undef ENABLE_NLS
/* Define if <sys/param.h> defines ntohl. */
#undef NTOHL_IN_SYS_PARAM_H
/* Define if the GNU gettext() function is already present or preinstalled. */
#undef HAVE_GETTEXT
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define if nanosleep is available. */
#undef HAVE_NANOSLEEP
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* long getopt support */
#undef HAVE_GETOPT_LONG
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* getopt support */
#undef HAVE_GETOPT_LONG
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define if <pthread.h> defines pthread_cond_t. */
#undef PTHREAD_COND_T_IN_PTHREAD_H
......@@ -374,66 +403,56 @@
/* Define if <pthread.h> defines pthread_once. */
#undef PTHREAD_ONCE_IN_PTHREAD_H
/* Define if <strings.h> defines strncasecmp. */
#undef STRNCASECMP_IN_STRINGS_H
/* Define if <time.h> defines nanosleep. */
#undef HAVE_DECL_NANOSLEEP
/* Define if <sys/time.h> defines struct timespec. */
#undef HAVE_STRUCT_TIMESPEC
/* Define if <X11/extensions/dpms.h> defines DPMSInfo. */
#undef DPMSINFO_IN_DPMS_H
/* Define if <sys/param.h> defines ntohl. */
#undef NTOHL_IN_SYS_PARAM_H
/* Support for variadic macros */
#undef HAVE_VARIADIC_MACROS
/* Maximum supported data alignment */
#undef ATTRIBUTE_ALIGNED_MAX
/* Define if $CC groks 3D Now! inline assembly. */
#undef CAN_COMPILE_3DNOW
/* Define if $CC groks SSE inline assembly. */
#undef CAN_COMPILE_SSE
/* Define if $CC groks AltiVec inline assembly. */
#undef CAN_COMPILE_ALTIVEC
/* Define if your compiler groks C AltiVec extensions. */
#undef CAN_COMPILE_C_ALTIVEC
/* Define if <pth.h> defines pth_init */
#undef PTH_INIT_IN_PTH_H
/* For FreeBSD VCD support */
#undef HAVE_IOC_TOC_HEADER_IN_SYS_CDIO_H
/* Define as the return type of signal handlers (`int' or `void'). */
#undef RETSIGTYPE
/* Indicate whether we should use SDL/SDL.h or SDL11/SDL.h */
#undef SDL_INCLUDE_FILE
/* big endian system */
#undef WORDS_BIGENDIAN
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
#undef STACK_DIRECTION
/* Define if <pth.h> defines pth_init */
#undef PTH_INIT_IN_PTH_H
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if <strings.h> defines strncasecmp. */
#undef STRNCASECMP_IN_STRINGS_H
/* Define if <st.h> defines st_init */
#undef ST_INIT_IN_ST_H
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Simple version string */
#undef VERSION_MESSAGE
/* Copyright string */
#undef COPYRIGHT_MESSAGE
/* Package name */
#undef VLC_PACKAGE
/* The ./configure command line */
#undef CONFIGURE_LINE
/* Package version */
#undef VLC_VERSION
/* String suffix for module functions */
#undef MODULE_SUFFIX
/* big endian system */
#undef WORDS_BIGENDIAN
/* Symbol suffix for module functions */
#undef MODULE_SYMBOL
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define as `__inline' if that's what the C compiler calls it, or to nothing
if it is not supported. */
#undef inline
/* Define to `long' if <sys/types.h> does not define. */
#undef off_t
/* Define to `unsigned' if <sys/types.h> does not define. */
#undef size_t
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: vlc_common.h,v 1.14 2002/08/07 00:29:36 sam Exp $
* $Id: vlc_common.h,v 1.15 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -173,9 +173,10 @@ VLC_DECLARE_STRUCT(stream_descriptor_t)
VLC_DECLARE_STRUCT(stream_sys_t)
/* Audio */
VLC_DECLARE_STRUCT(aout_thread_t)
VLC_DECLARE_STRUCT(aout_sys_t)
VLC_DECLARE_STRUCT(aout_fifo_t)
VLC_DECLARE_STRUCT(aout_instance_t)
VLC_DECLARE_STRUCT(aout_input_t)
VLC_DECLARE_STRUCT(aout_buffer_t)
VLC_DECLARE_STRUCT(audio_sample_format_t)
/* Video */
VLC_DECLARE_STRUCT(vout_thread_t)
......
......@@ -2,7 +2,10 @@
struct module_symbols_t
{
aout_fifo_t * (* __aout_CreateFifo_inner) ( vlc_object_t *, int, int, int, int, void * ) ;
aout_buffer_t * (* aout_BufferNew_inner) ( aout_instance_t *, aout_input_t *, size_t ) ;
aout_buffer_t * (* aout_OutputNextBuffer_inner) ( aout_instance_t *, mtime_t ) ;
aout_input_t * (* __aout_InputNew_inner) ( vlc_object_t *, aout_instance_t **, audio_sample_format_t * ) ;
aout_instance_t * (* __aout_NewInstance_inner) ( vlc_object_t * ) ;
char * (* __config_GetPsz_inner) (vlc_object_t *, const char *) ;
char * (* config_GetHomeDir_inner) ( void ) ;
char * (* input_OffsetToTime_inner) ( input_thread_t *, char *, off_t ) ;
......@@ -95,7 +98,10 @@ struct module_symbols_t
void (* __vlc_object_yield_inner) ( vlc_object_t * ) ;
void (* __vlc_thread_join_inner) ( vlc_object_t *, char *, int ) ;
void (* __vlc_thread_ready_inner) ( vlc_object_t * ) ;
void (* aout_DestroyFifo_inner) ( aout_fifo_t *p_fifo ) ;
void (* aout_BufferDelete_inner) ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) ;
void (* aout_BufferPlay_inner) ( aout_instance_t *, aout_input_t *, aout_buffer_t * ) ;
void (* aout_DeleteInstance_inner) ( aout_instance_t * ) ;
void (* aout_InputDelete_inner) ( aout_instance_t *, aout_input_t * ) ;
void (* config_Duplicate_inner) ( module_t *, module_config_t * ) ;
void (* config_SetCallbacks_inner) ( module_config_t *, module_config_t * ) ;
void (* config_UnsetCallbacks_inner) ( module_config_t * ) ;
......@@ -146,7 +152,8 @@ struct module_symbols_t
# define UnalignedGetBits p_symbols->UnalignedGetBits_inner
# define UnalignedRemoveBits p_symbols->UnalignedRemoveBits_inner
# define UnalignedShowBits p_symbols->UnalignedShowBits_inner
# define __aout_CreateFifo p_symbols->__aout_CreateFifo_inner
# define __aout_InputNew p_symbols->__aout_InputNew_inner
# define __aout_NewInstance p_symbols->__aout_NewInstance_inner
# define __config_GetFloat p_symbols->__config_GetFloat_inner
# define __config_GetInt p_symbols->__config_GetInt_inner
# define __config_GetPsz p_symbols->__config_GetPsz_inner
......@@ -193,7 +200,12 @@ struct module_symbols_t
# define __vlc_threads_end p_symbols->__vlc_threads_end_inner
# define __vlc_threads_init p_symbols->__vlc_threads_init_inner
# define __vout_CreateThread p_symbols->__vout_CreateThread_inner
# define aout_DestroyFifo p_symbols->aout_DestroyFifo_inner
# define aout_BufferDelete p_symbols->aout_BufferDelete_inner
# define aout_BufferNew p_symbols->aout_BufferNew_inner
# define aout_BufferPlay p_symbols->aout_BufferPlay_inner
# define aout_DeleteInstance p_symbols->aout_DeleteInstance_inner
# define aout_InputDelete p_symbols->aout_InputDelete_inner
# define aout_OutputNextBuffer p_symbols->aout_OutputNextBuffer_inner
# define config_Duplicate p_symbols->config_Duplicate_inner
# define config_FindConfig p_symbols->config_FindConfig_inner
# define config_GetHomeDir p_symbols->config_GetHomeDir_inner
......
float32tos16_SOURCES = float32tos16.c
/*****************************************************************************
* float32tos16.c : trivial mixer plug-in (1 input, no downmixing)
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: float32tos16.c,v 1.1 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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 <errno.h>
#include <stdlib.h> /* malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#include "audio_output.h"
#include "aout_internal.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Create ( vlc_object_t * );
static void DoWork ( aout_instance_t *, aout_filter_t *, aout_buffer_t *,
aout_buffer_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("aout filter for float32->s16 conversion") );
set_capability( "audio filter", 1 );
set_callbacks( Create, NULL );
vlc_module_end();
/*****************************************************************************
* Create: allocate trivial mixer
*****************************************************************************
* This function allocates and initializes a Crop vout method.
*****************************************************************************/
static int Create( vlc_object_t *p_this )
{
aout_filter_t * p_filter = (aout_filter_t *)p_this;
if ( p_filter->input.i_format != AOUT_FMT_FLOAT32
&& p_filter->output.i_format != AOUT_FMT_S16_NE )
{
return -1;
}
if ( p_filter->input.i_rate != p_filter->output.i_rate
|| p_filter->input.i_channels != p_filter->output.i_channels )
{
return -1;
}
p_filter->pf_do_work = DoWork;
p_filter->b_in_place = 1;
return 0;
}
/*****************************************************************************
* DoWork: convert a buffer
*****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_filter_t * p_filter,
aout_buffer_t * p_in_buf, aout_buffer_t * p_out_buf )
{
int i;
float * p_in = (float *)p_in_buf->p_buffer;
s16 * p_out = (s16 *)p_out_buf->p_buffer;
for ( i = 0; i < p_in_buf->i_nb_samples * p_filter->input.i_channels; i++ )
{
if ( *p_in >= 1.0 ) *p_out = 32767;
else if ( *p_in < -1.0 ) *p_out = -32768;
else *p_out = *p_in * 32768.0;
p_in++; p_out++;
}
}
trivial_SOURCES = trivial.c
/*****************************************************************************
* trivial.c : trivial mixer plug-in (1 input, no downmixing)
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: trivial.c,v 1.1 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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 <errno.h>
#include <stdlib.h> /* malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#include "audio_output.h"
#include "aout_internal.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Create ( vlc_object_t * );
static void DoWork ( aout_instance_t *, aout_buffer_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("trivial aout mixer module") );
set_capability( "audio mixer", 1 );
add_shortcut( "trivial" );
set_callbacks( Create, NULL );
vlc_module_end();
/*****************************************************************************
* Create: allocate trivial mixer
*****************************************************************************
* This function allocates and initializes a Crop vout method.
*****************************************************************************/
static int Create( vlc_object_t *p_this )
{
aout_instance_t * p_aout = (aout_instance_t *)p_this;
if ( p_aout->mixer.output.i_format != AOUT_FMT_FLOAT32
&& p_aout->mixer.output.i_format != AOUT_FMT_FIXED32 )
{
return -1;
}
p_aout->mixer.pf_do_work = DoWork;
return 0;
}
/*****************************************************************************
* SparseCopy: trivially downmix or upmix a buffer
*****************************************************************************/
static void SparseCopy( u32 * p_dest, const u32 * p_src, size_t i_len,
int i_output_stride, int i_input_stride )
{
int i;
for ( i = 0; i < i_len; i++ )
{
int j;
for ( j = 0; j < i_output_stride; j++ )
{
p_dest[j] = p_src[j];
}
p_src += i_input_stride;
p_dest += i_output_stride;
}
}
/*****************************************************************************
* DoWork: mix a new output buffer
*****************************************************************************/
static void DoWork( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
{
aout_input_t * p_input = p_aout->pp_inputs[0];
if ( p_input->input.i_channels == p_aout->mixer.output.i_channels )
{
int i_nb_bytes = p_buffer->i_nb_samples * sizeof(u32)
* p_input->input.i_channels;
char * p_in = (p_input->p_first_byte_to_mix == NULL) ?
p_input->fifo.p_first->p_buffer :
p_input->p_first_byte_to_mix;
char * p_out = p_buffer->p_buffer;
for ( ; ; )
{
ptrdiff_t i_available_bytes = (p_input->fifo.p_first->p_buffer
- p_in)
+ p_input->fifo.p_first->i_nb_samples
* sizeof(u32)
* p_input->input.i_channels;
if ( i_available_bytes < i_nb_bytes )
{
aout_buffer_t * p_old_buffer;
if ( i_available_bytes > 0 )
p_aout->p_vlc->pf_memcpy( p_out, p_in, i_available_bytes );
i_nb_bytes -= i_available_bytes;
p_out += i_available_bytes;
/* Next buffer */
p_old_buffer = aout_FifoPop( p_aout, &p_input->fifo );
aout_BufferFree( p_old_buffer );
if ( p_input->fifo.p_first == NULL )
{
msg_Err( p_aout, "internal amix error" );
return;
}
p_in = p_input->fifo.p_first->p_buffer;
}
else
{
p_aout->p_vlc->pf_memcpy( p_out, p_in, i_nb_bytes );
p_input->p_first_byte_to_mix = p_in + i_nb_bytes;
break;
}
}
}
else
{
/* Downmixing or upmixing. */
int i_nb_samples = p_buffer->i_nb_samples;
u32 * p_in = (p_input->p_first_byte_to_mix == NULL) ?
(u32 *)p_input->fifo.p_first->p_buffer :
(u32 *)p_input->p_first_byte_to_mix;
u32 * p_out = (u32 *)p_buffer->p_buffer;
if ( p_input->input.i_channels < p_aout->mixer.output.i_channels )
{
/* Zero out the destination buffer, to avoid static on unavailable
* channels. */
memset( p_buffer->p_buffer, 0,
p_buffer->i_nb_samples * sizeof(u32)
* p_aout->mixer.output.i_channels );
}
for ( ; ; )
{
ptrdiff_t i_available_bytes = (p_input->fifo.p_first->p_buffer
- (char *)p_in)
+ p_input->fifo.p_first->i_nb_samples
* sizeof(u32)
* p_input->input.i_channels;
int i_available_samples = i_available_bytes
/ p_input->input.i_channels
/ sizeof(u32);
if ( i_available_samples < i_nb_samples )
{
aout_buffer_t * p_old_buffer;
if ( i_available_samples > 0 )
SparseCopy( p_out, p_in, i_available_samples,
p_aout->mixer.output.i_channels,
p_input->input.i_channels );
i_nb_samples -= i_available_samples;
p_out += i_available_samples * p_aout->mixer.output.i_channels;
/* Next buffer */
p_old_buffer = aout_FifoPop( p_aout, &p_input->fifo );
aout_BufferFree( p_old_buffer );
if ( p_input->fifo.p_first == NULL )
{
msg_Err( p_aout, "internal amix error" );
return;
}
p_in = (u32 *)p_input->fifo.p_first->p_buffer;
}
else
{
SparseCopy( p_out, p_in, i_nb_samples,
p_aout->mixer.output.i_channels,
p_input->input.i_channels );
p_input->p_first_byte_to_mix = (char *)p_in
+ i_nb_samples * p_input->input.i_channels
* sizeof(u32);
break;
}
}
}
}
alsa_SOURCES = alsa.c
arts_SOURCES = arts.c
esd_SOURCES = esd.c
file_SOURCES = file.c
oss_SOURCES = oss.c
waveout_SOURCES = waveout.c
......@@ -2,7 +2,7 @@
* alsa.c : alsa plugin for vlc
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: alsa.c,v 1.1 2002/08/04 17:23:42 sam Exp $
* $Id: alsa.c,v 1.1 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Henri Fallon <henri@videolan.org> - Original Author
* Jeffrey Baker <jwbaker@acm.org> - Port to ALSA 1.0 API
......
......@@ -2,7 +2,7 @@
* esd.c : EsounD module
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: esd.c,v 1.1 2002/08/04 17:23:42 sam Exp $
* $Id: esd.c,v 1.1 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......
/*****************************************************************************
* file.c : audio output which writes the samples to a file
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: file.c,v 1.1 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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 <string.h>
#include <stdlib.h>
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include "aout_internal.h"
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int SetFormat ( aout_instance_t * );
static void Play ( aout_instance_t *, aout_buffer_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define FORMAT_TEXT N_("Output format")
#define FORMAT_LONGTEXT N_("one of \"u8\", \"s8\", \"u16\", \"s16\"," \
" \"u16_le\", \"s16_le\", \"u16_be\"," \
" \"s16_be\", \"fixed32\", \"float32\" or \"spdif\"")
static char *format_list[] = { "u8", "s8", "u16", "s16", "u16_le", "s16_le",
"u16_be", "s16_be", "fixed32", "float32",
"spdif", NULL };
static int format_int[] = { AOUT_FMT_U8, AOUT_FMT_S8, AOUT_FMT_U16_NE,
AOUT_FMT_S16_NE, AOUT_FMT_U16_LE, AOUT_FMT_S16_LE,
AOUT_FMT_U16_BE, AOUT_FMT_S16_BE, AOUT_FMT_FIXED32,
AOUT_FMT_FLOAT32, AOUT_FMT_A52 };
#define PATH_TEXT N_("Path of the output file")
#define PATH_LONGTEXT N_("By default samples.raw")
vlc_module_begin();
add_category_hint( N_("Audio"), NULL );
add_string_from_list( "format", "s16", format_list, NULL,
FORMAT_TEXT, FORMAT_LONGTEXT );
add_string( "path", "samples.raw", NULL, PATH_TEXT, PATH_LONGTEXT );
set_description( _("file output module") );
set_capability( "audio output", 0 );
add_shortcut( "file" );
set_callbacks( Open, Close );
vlc_module_end();
/*****************************************************************************
* Open: open a dummy audio device
*****************************************************************************/
static int Open( vlc_object_t * p_this )
{
aout_instance_t * p_aout = (aout_instance_t *)p_this;
FILE * p_file;
char * psz_name = config_GetPsz( p_this, "path" );
(FILE *)p_aout->output.p_sys = p_file = fopen( psz_name, "wb" );
free( psz_name );
if ( p_file == NULL ) return -1;
p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
return VLC_SUCCESS;
}
/*****************************************************************************
* Close: close our file
*****************************************************************************/
static void Close( vlc_object_t * p_this )
{
aout_instance_t * p_aout = (aout_instance_t *)p_this;
fclose( (FILE *)p_aout->output.p_sys );
}
/*****************************************************************************
* SetFormat: pretend to set the dsp output format
*****************************************************************************/
static int SetFormat( aout_instance_t * p_aout )
{
char * psz_format = config_GetPsz( p_aout, "format" );
char ** ppsz_compare = format_list;
int i = 0;
while ( *ppsz_compare != NULL )
{
if ( !strncmp( *ppsz_compare, psz_format, strlen(*ppsz_compare) ) )
{
break;
}
ppsz_compare++; i++;
}
if ( *ppsz_compare == NULL )
{
msg_Err( p_aout, "Cannot understand the format string (%s)",
psz_format );
return -1;
}
p_aout->output.output.i_format = format_int[i];
p_aout->output.i_nb_samples = 2048;
return 0;
}
/*****************************************************************************
* Play: pretend to play a sound
*****************************************************************************/
static void Play( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
{
if( fwrite( p_buffer->p_buffer,
p_buffer->i_nb_samples
* aout_FormatToBytes( &p_aout->output.output ), 1,
(FILE *)p_aout->output.p_sys ) != 1 )
{
msg_Err( p_aout, "write error (%s)", strerror(errno) );
}
aout_BufferFree( p_buffer );
}
/*****************************************************************************
* dsp.c : OSS /dev/dsp module for vlc
* oss.c : OSS /dev/dsp module for vlc
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: dsp.c,v 1.1 2002/08/04 17:23:42 sam Exp $
* Copyright (C) 2000-2002 VideoLAN
* $Id: oss.c,v 1.1 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
* Christophe Massiot <massiot@via.ecp.fr>
*
* 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
......@@ -33,7 +34,13 @@
#include <stdlib.h> /* calloc(), malloc(), free() */
#include <vlc/vlc.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#include <vlc/aout.h>
#include "aout_internal.h"
/* SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT, SNDCTL_DSP_STEREO, SNDCTL_DSP_SPEED,
* SNDCTL_DSP_GETOSPACE */
......@@ -46,35 +53,34 @@
#endif
/*****************************************************************************
* aout_sys_t: dsp audio output method descriptor
* aout_sys_t: OSS audio output method descriptor
*****************************************************************************
* This structure is part of the audio output thread descriptor.
* It describes the dsp specific properties of an audio device.
*****************************************************************************/
struct aout_sys_t
{
audio_buf_info audio_buf;
/* Path to the audio output device */
char * psz_device;
int i_fd;
volatile vlc_bool_t b_die;
};
#define DEFAULT_FRAME_SIZE 2048
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * );
static int SetFormat ( aout_thread_t * );
static int GetBufInfo ( aout_thread_t *, int );
static void Play ( aout_thread_t *, byte_t *, int );
static int SetFormat ( aout_instance_t * );
static void Play ( aout_instance_t *, aout_buffer_t * );
static int OSSThread ( aout_instance_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
add_category_hint( N_("Miscellaneous"), NULL );
add_category_hint( N_("Audio"), NULL );
add_file( "dspdev", "/dev/dsp", NULL, N_("OSS dsp device"), NULL );
set_description( _("Linux OSS /dev/dsp module") );
set_capability( "audio output", 100 );
......@@ -82,122 +88,163 @@ vlc_module_begin();
vlc_module_end();
/*****************************************************************************
* Open: opens the audio device (the digital sound processor)
* Open: open 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->p_sys->i_fd with the file's descriptor.
*****************************************************************************/
static int Open( vlc_object_t *p_this )
{
aout_thread_t *p_aout = (aout_thread_t *)p_this;
aout_instance_t * p_aout = (aout_instance_t *)p_this;
struct aout_sys_t * p_sys;
char * psz_device;
/* Allocate structure */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) );
if( p_sys == NULL )
{
msg_Err( p_aout, "out of memory" );
return( 1 );
return 1;
}
/* Initialize some variables */
if( !(p_aout->p_sys->psz_device = config_GetPsz( p_aout, "dspdev" )) )
if( (psz_device = config_GetPsz( p_aout, "dspdev" )) == NULL )
{
msg_Err( p_aout, "don't know which audio device to open" );
msg_Err( p_aout, "no audio device given (maybe /dev/dsp ?)" );
free( p_aout->p_sys );
return( -1 );
return -1;
}
p_aout->pf_setformat = SetFormat;
p_aout->pf_getbufinfo = GetBufInfo;
p_aout->pf_play = Play;
/* Open the sound device */
if( (p_aout->p_sys->i_fd = open( p_aout->p_sys->psz_device, O_WRONLY ))
< 0 )
if( (p_sys->i_fd = open( psz_device, O_WRONLY )) < 0 )
{
msg_Err( p_aout, "cannot open audio device (%s)",
p_aout->p_sys->psz_device );
psz_device );
free( psz_device );
free( p_sys );
return -1;
}
free( psz_device );
/* Create OSS thread and wait for its readiness. */
p_sys->b_die = 0;
if( vlc_thread_create( p_aout, "aout", OSSThread, VLC_TRUE ) )
{
msg_Err( p_input, "cannot create OSS thread (%s)", strerror(errno) );
free( p_aout->p_sys->psz_device );
free( p_aout->p_sys );
return( -1 );
return -1;
}
return( 0 );
p_aout->pf_setformat = SetFormat;
p_aout->pf_play = Play;
return 0;
}
/*****************************************************************************
* SetFormat: resets the dsp and sets its format
* SetFormat: reset the dsp and set 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 SetFormat( aout_thread_t *p_aout )
static int SetFormat( aout_instance_t *p_aout )
{
struct aout_sys_t * p_sys = p_aout->output.p_sys;
int i_format;
int i_rate;
vlc_bool_t b_stereo;
/* Reset the DSP device */
if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
if( ioctl( p_sys->i_fd, SNDCTL_DSP_RESET, NULL ) < 0 )
{
msg_Err( p_aout, "cannot reset audio device (%s)",
p_aout->p_sys->psz_device );
return( -1 );
msg_Err( p_aout, "cannot reset OSS audio device" );
return -1;
}
/* Set the output format */
i_format = p_aout->i_format;
if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0 )
i_format = AOUT_FMT_S16_NE;
if( ioctl( p_sys->i_fd, SNDCTL_DSP_SETFMT, &i_format ) < 0
|| i_format != AOUT_FMT_S16_NE )
{
msg_Err( p_aout, "cannot set audio output format (%i)",
p_aout->i_format );
return( -1 );
i_format );
return -1;
}
p_aout->output.output.i_format = AOUT_FMT_S16_NE;
if( i_format != p_aout->i_format )
/* FIXME */
if ( p_aout->output.output.i_channels > 2 )
{
msg_Warn( p_aout, "audio output format not supported (%i)",
p_aout->i_format );
p_aout->i_format = i_format;
msg_Warn( p_aout, "only two channels are supported at the moment" );
/* Trigger downmixing */
p_aout->output.output.i_channels = 2;
}
/* Set the number of channels */
b_stereo = ( p_aout->i_channels >= 2 );
b_stereo = p_aout->output.output.i_channels - 1;
if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_STEREO, &b_stereo ) < 0 )
if( ioctl( p_sys->i_fd, SNDCTL_DSP_STEREO, &b_stereo ) < 0 )
{
msg_Err( p_aout, "cannot set number of audio channels (%i)",
p_aout->i_channels );
return( -1 );
p_aout->output.output.i_channels );
return -1;
}
if( (1 + b_stereo) != p_aout->i_channels )
if ( b_stereo + 1 != p_aout->output.output.i_channels )
{
msg_Warn( p_aout, "%i audio channels not supported",
p_aout->i_channels );
p_aout->i_channels = 1 + b_stereo;
msg_Warn( p_aout, "driver forced up/downmixing %li->%li",
p_aout->output.output.i_channels,
b_stereo + 1 );
p_aout->output.output.i_channels = b_stereo + 1;
}
/* Set the output rate */
i_rate = p_aout->i_rate;
i_rate = p_aout->output.output.i_rate;
if( ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_SPEED, &i_rate ) < 0 )
{
msg_Err( p_aout, "cannot set audio output rate (%i)", p_aout->i_rate );
return( -1 );
return -1;
}
if( i_rate != p_aout->i_rate )
if( i_rate != p_aout->output.output.i_rate )
{
msg_Warn( p_aout, "audio output rate not supported (%li)",
p_aout->i_rate );
p_aout->i_rate = i_rate;
msg_Warn( p_aout, "driver forced resampling %li->%li",
p_aout->output.output.i_rate, i_rate );
p_aout->output.output.i_rate = i_rate;
}
return( 0 );
p_aout->output.i_nb_samples = DEFAULT_FRAME_SIZE;
return 0;
}
/*****************************************************************************
* Play: queue a buffer for playing by OSSThread
*****************************************************************************/
static void Play( aout_instance_t *p_aout, aout_buffer_t * p_buffer )
{
aout_FifoPush( p_aout, &p_aout->output.fifo, p_buffer );
}
/*****************************************************************************
* Close: close the dsp audio device
*****************************************************************************/
static void Close( vlc_object_t * p_this )
{
aout_instance_t *p_aout = (aout_instance_t *)p_this;
struct aout_sys_t * p_sys = p_aout->output.p_sys;
p_sys->b_die = 1;
vlc_thread_join( p_aout );
close( p_aout->p_sys->i_fd );
free( p_aout->p_sys );
}
/*****************************************************************************
* GetBufInfo: buffer status query
*****************************************************************************
......@@ -208,40 +255,64 @@ static int SetFormat( aout_thread_t *p_aout )
* - int bytes : available space in bytes (includes partially used fragments)
* Note! 'bytes' could be more than fragments*fragsize
*****************************************************************************/
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
static int GetBufInfo( aout_instance_t * p_aout )
{
ioctl( p_aout->p_sys->i_fd, SNDCTL_DSP_GETOSPACE,
&p_aout->p_sys->audio_buf );
struct aout_sys_t * p_sys = p_aout->output.p_sys;
audio_buf_info audio_buf;
ioctl( p_sys->i_fd, SNDCTL_DSP_GETOSPACE, &audio_buf );
/* returns the allocated space in bytes */
return ( (p_aout->p_sys->audio_buf.fragstotal
* p_aout->p_sys->audio_buf.fragsize)
- p_aout->p_sys->audio_buf.bytes );
return ( (audio_buf.fragstotal * audio_buf.fragsize) - audio_buf.bytes );
}
/*****************************************************************************
* Play: plays a sound samples buffer
*****************************************************************************
* This function writes a buffer of i_length bytes in the dsp
* OSSThread: asynchronous thread used to DMA the data to the device
*****************************************************************************/
static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
static int OSSThread( aout_instance_t * p_aout )
{
struct aout_sys_t * p_sys = p_aout->output.p_sys;
while ( !p_sys->b_die )
{
int i_bytes_per_sample = aout_FormatToBytes( &p_aout->output.output );
aout_buffer_t * p_buffer;
mtime_t next_date;
int i_tmp;
i_tmp = write( p_aout->p_sys->i_fd, buffer, i_size );
char * p_bytes;
/* Get the presentation date of the next write() operation. It
* is equal to the current date + duration of buffered samples.
* Order is important here, since GetBufInfo is believed to take
* more time than mdate(). */
next_date = (mtime_t)GetBufInfo( p_aout ) * 1000000
/ i_bytes_per_sample
/ p_aout->output.output.i_rate;
next_date += mdate();
p_buffer = aout_OutputNextBuffer( p_aout, next_date );
if ( p_buffer != NULL )
{
p_bytes = p_buffer->p_buffer;
}
else
{
p_bytes = alloca( DEFAULT_FRAME_SIZE * i_bytes_per_sample );
memset( p_bytes, 0, DEFAULT_FRAME_SIZE * i_bytes_per_sample );
}
i_tmp = write( p_sys->i_fd, p_bytes,
DEFAULT_FRAME_SIZE * i_bytes_per_sample );
if( i_tmp < 0 )
{
msg_Err( p_aout, "write failed (%s)", strerror(errno) );
}
}
/*****************************************************************************
* Close: closes the dsp audio device
*****************************************************************************/
static void Close( vlc_object_t *p_this )
{
aout_thread_t *p_aout = (aout_thread_t *)p_this;
close( p_aout->p_sys->i_fd );
free( p_aout->p_sys->psz_device );
if ( p_buffer != NULL )
{
aout_BufferFree( p_buffer );
}
}
}
......@@ -2,7 +2,7 @@
* waveout.c : Windows waveOut plugin for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: waveout.c,v 1.1 2002/08/04 17:23:42 sam Exp $
* $Id: waveout.c,v 1.1 2002/08/07 21:36:55 massiot Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......
......@@ -3,10 +3,11 @@
* This plugin makes use of liba52 to decode A/52 audio
* (http://liba52.sf.net/).
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: a52.c,v 1.1 2002/08/04 17:23:42 sam Exp $
* Copyright (C) 2001, 2002 VideoLAN
* $Id: a52.c,v 1.2 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
* Christophe Massiot <massiot@via.ecp.fr>
*
* 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
......@@ -48,30 +49,15 @@
#define A52DEC_FRAME_SIZE 1536
/*
* Global lock for accessing liba52 functions.
* Currently, liba52 isn't thread-safe. So to prevent two threads from
* using liba52 at the same time, we have to set up a global lock.
* I know static variables aren't a good idea in multi-threaded programs,
* but believe me, this is the way to go.
* --Meuuh 2002-07-19
*/
static vlc_mutex_t a52_lock;
static vlc_bool_t b_liba52_initialized = 0;
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int OpenDecoder ( vlc_object_t * );
static int RunDecoder ( decoder_fifo_t * );
static int DecodeFrame ( a52_adec_thread_t * );
static int InitThread ( a52_adec_thread_t * );
static void EndThread ( a52_adec_thread_t * );
static void BitstreamCallback ( bit_stream_t *, vlc_bool_t );
static void float2s16_2 ( float *, int16_t * );
static inline int16_t convert ( int32_t );
static int DecodeFrame ( a52_thread_t *, u8 * );
static int InitThread ( a52_thread_t *, decoder_fifo_t * );
static void EndThread ( a52_thread_t * );
/*****************************************************************************
* Module descriptor
......@@ -116,208 +102,211 @@ static int OpenDecoder( vlc_object_t *p_this )
*****************************************************************************/
static int RunDecoder( decoder_fifo_t *p_fifo )
{
a52_adec_thread_t *p_a52_adec;
a52_thread_t *p_a52;
/* Allocate the memory needed to store the thread's structure */
p_a52_adec = (a52_adec_thread_t *)malloc( sizeof(a52_adec_thread_t) );
if (p_a52_adec == NULL)
p_a52 = (a52_thread_t *)malloc( sizeof(a52_thread_t) );
if( p_a52 == NULL )
{
msg_Err( p_fifo, "out of memory" );
DecoderError( p_fifo );
return( -1 );
return -1;
}
/* FIXME */
p_a52_adec->i_channels = 2;
/*
* Initialize the thread properties
*/
p_a52_adec->p_aout_fifo = NULL;
p_a52_adec->p_fifo = p_fifo;
if( InitThread( p_a52_adec ) )
if( InitThread( p_a52, p_fifo ) )
{
msg_Err( p_a52_adec->p_fifo, "could not initialize thread" );
msg_Err( p_a52->p_fifo, "could not initialize thread" );
DecoderError( p_fifo );
free( p_a52_adec );
return( -1 );
free( p_a52 );
return -1;
}
/* liba52 decoder thread's main loop */
while( !p_a52_adec->p_fifo->b_die && !p_a52_adec->p_fifo->b_error )
while( !p_a52->p_fifo->b_die && !p_a52->p_fifo->b_error )
{
/* look for sync word - should be 0x0b77 */
RealignBits(&p_a52_adec->bit_stream);
while( (ShowBits( &p_a52_adec->bit_stream, 16 ) ) != 0x0b77 &&
(!p_a52_adec->p_fifo->b_die) && (!p_a52_adec->p_fifo->b_error))
int i_frame_size, i_flags, i_rate, i_bit_rate;
mtime_t pts;
/* Temporary buffer to store the raw frame to be decoded */
u8 p_frame_buffer[3840];
/* Look for sync word - should be 0x0b77 */
RealignBits(&p_a52->bit_stream);
while( (ShowBits( &p_a52->bit_stream, 16 ) ) != 0x0b77 &&
(!p_a52->p_fifo->b_die) && (!p_a52->p_fifo->b_error))
{
RemoveBits( &p_a52_adec->bit_stream, 8 );
RemoveBits( &p_a52->bit_stream, 8 );
}
/* get a52 frame header */
GetChunk( &p_a52_adec->bit_stream, p_a52_adec->p_frame_buffer, 7 );
if( p_a52_adec->p_fifo->b_die ) break;
/* Get A/52 frame header */
GetChunk( &p_a52->bit_stream, p_frame_buffer, 7 );
if( p_a52->p_fifo->b_die ) break;
/* check if frame is valid and get frame info */
vlc_mutex_lock( &a52_lock );
p_a52_adec->frame_size = a52_syncinfo( p_a52_adec->p_frame_buffer,
&p_a52_adec->flags,
&p_a52_adec->sample_rate,
&p_a52_adec->bit_rate );
vlc_mutex_unlock( &a52_lock );
/* Check if frame is valid and get frame info */
i_frame_size = a52_syncinfo( p_frame_buffer, &i_flags, &i_rate,
&i_bit_rate );
if( !p_a52_adec->frame_size )
if( !i_frame_size )
{
msg_Warn( p_a52_adec->p_fifo, "a52_syncinfo failed" );
msg_Warn( p_a52->p_fifo, "a52_syncinfo failed" );
continue;
}
if( DecodeFrame( p_a52_adec ) && !p_a52_adec->p_fifo->b_die )
if( (p_a52->p_aout_input != NULL) &&
( (p_a52->output_format.i_rate != i_rate)
/* || (p_a52->output_format.i_channels != i_channels) */ ) )
{
DecoderError( p_fifo );
free( p_a52_adec );
return( -1 );
/* Parameters changed - this should not happen. */
aout_InputDelete( p_a52->p_aout, p_a52->p_aout_input );
p_a52->p_aout_input = NULL;
}
/* Creating the audio input if not created yet. */
if( p_a52->p_aout_input == NULL )
{
p_a52->output_format.i_rate = i_rate;
/* p_a52->output_format.i_channels = i_channels; */
p_a52->p_aout_input = aout_InputNew( p_a52->p_fifo,
&p_a52->p_aout,
&p_a52->output_format );
if ( p_a52->p_aout_input == NULL )
{
p_a52->p_fifo->b_error = 1;
break;
}
}
/* Set the Presentation Time Stamp */
CurrentPTS( &p_a52->bit_stream, &pts, NULL );
if ( pts != 0 )
{
p_a52->last_date = pts;
}
/* Get the complete frame */
GetChunk( &p_a52->bit_stream, p_frame_buffer + 7,
i_frame_size - 7 );
if( p_a52->p_fifo->b_die ) break;
if( DecodeFrame( p_a52, p_frame_buffer ) )
{
p_a52->p_fifo->b_error = 1;
break;
}
}
/* If b_error is set, the decoder thread enters the error loop */
if( p_a52_adec->p_fifo->b_error )
if( p_a52->p_fifo->b_error )
{
DecoderError( p_a52_adec->p_fifo );
DecoderError( p_a52->p_fifo );
}
/* End of the liba52 decoder thread */
EndThread( p_a52_adec );
EndThread( p_a52 );
return( 0 );
return 0;
}
/*****************************************************************************
* InitThread: initialize data before entering main loop
*****************************************************************************/
static int InitThread( a52_adec_thread_t * p_a52_adec )
static int InitThread( a52_thread_t * p_a52, decoder_fifo_t * p_fifo )
{
/* Initialize the global lock */
vlc_mutex_lock( p_a52_adec->p_fifo->p_vlc->p_global_lock );
if ( !b_liba52_initialized )
{
vlc_mutex_init( p_a52_adec->p_fifo, &a52_lock );
b_liba52_initialized = 1;
}
vlc_mutex_unlock( p_a52_adec->p_fifo->p_vlc->p_global_lock );
/* Initialize the thread properties */
p_a52->p_aout = NULL;
p_a52->p_aout_input = NULL;
p_a52->p_fifo = p_fifo;
p_a52->output_format.i_format = AOUT_FMT_FLOAT32;
p_a52->output_format.i_channels = 2; /* FIXME ! */
p_a52->last_date = 0;
/* Initialize liba52 */
vlc_mutex_lock( &a52_lock );
p_a52_adec->p_a52_state = a52_init( 0 );
vlc_mutex_unlock( &a52_lock );
if( p_a52_adec->p_a52_state == NULL )
p_a52->p_a52_state = a52_init( 0 );
if( p_a52->p_a52_state == NULL )
{
msg_Err( p_a52_adec->p_fifo, "unable to initialize liba52" );
msg_Err( p_a52->p_fifo, "unable to initialize liba52" );
return -1;
}
p_a52_adec->b_dynrng = config_GetInt( p_a52_adec->p_fifo, "a52-dynrng" );
p_a52->b_dynrng = config_GetInt( p_a52->p_fifo, "a52-dynrng" );
/* Init the BitStream */
InitBitstream( &p_a52_adec->bit_stream,
p_a52_adec->p_fifo,
BitstreamCallback, NULL );
InitBitstream( &p_a52->bit_stream, p_a52->p_fifo,
NULL, NULL );
return( 0 );
return 0;
}
/*****************************************************************************
* DecodeFrame: decodes an ATSC A/52 frame.
* Interleave: helper function to interleave channels
*****************************************************************************/
static int DecodeFrame( a52_adec_thread_t * p_a52_adec )
static void Interleave( float * p_out, float * p_in, int i_channels )
{
sample_t sample_level = 1;
byte_t *p_buffer;
int i;
if( ( p_a52_adec->p_aout_fifo != NULL ) &&
( p_a52_adec->p_aout_fifo->i_rate != p_a52_adec->sample_rate ) )
{
/* Make sure the output thread leaves the NextFrame() function */
vlc_mutex_lock (&(p_a52_adec->p_aout_fifo->data_lock));
aout_DestroyFifo (p_a52_adec->p_aout_fifo);
vlc_cond_signal (&(p_a52_adec->p_aout_fifo->data_wait));
vlc_mutex_unlock (&(p_a52_adec->p_aout_fifo->data_lock));
int i, j;
p_a52_adec->p_aout_fifo = NULL;
}
/* Creating the audio output fifo if not created yet */
if( p_a52_adec->p_aout_fifo == NULL )
for ( j = 0; j < i_channels; j++ )
{
p_a52_adec->p_aout_fifo = aout_CreateFifo( p_a52_adec->p_fifo,
AOUT_FIFO_PCM, p_a52_adec->i_channels,
p_a52_adec->sample_rate,
A52DEC_FRAME_SIZE * p_a52_adec->i_channels,
NULL );
if ( p_a52_adec->p_aout_fifo == NULL )
for ( i = 0; i < 256; i++ )
{
return( -1 );
p_out[i * i_channels + j] = p_in[j * 256 + i];
}
}
}
/* Set the Presentation Time Stamp */
CurrentPTS( &p_a52_adec->bit_stream,
&p_a52_adec->p_aout_fifo->date[
p_a52_adec->p_aout_fifo->i_end_frame],
NULL );
/*****************************************************************************
* DecodeFrame: decode an ATSC A/52 frame.
*****************************************************************************/
static int DecodeFrame( a52_thread_t * p_a52, u8 * p_frame_buffer )
{
sample_t i_sample_level = 1;
aout_buffer_t * p_buffer;
int i, i_flags;
int i_bytes_per_block = 256 * p_a52->output_format.i_channels
* sizeof(float);
if( !p_a52_adec->p_aout_fifo->date[
p_a52_adec->p_aout_fifo->i_end_frame] )
if( !p_a52->last_date )
{
p_a52_adec->p_aout_fifo->date[
p_a52_adec->p_aout_fifo->i_end_frame] = LAST_MDATE;
/* We've just started the stream, wait for the first PTS. */
return 0;
}
p_buffer = ((byte_t *)p_a52_adec->p_aout_fifo->buffer) +
( p_a52_adec->p_aout_fifo->i_end_frame * A52DEC_FRAME_SIZE *
p_a52_adec->i_channels * sizeof(s16) );
p_buffer = aout_BufferNew( p_a52->p_aout, p_a52->p_aout_input,
A52DEC_FRAME_SIZE );
if ( p_buffer == NULL ) return -1;
p_buffer->start_date = p_a52->last_date;
p_a52->last_date += (mtime_t)(A52DEC_FRAME_SIZE * 1000000)
/ p_a52->output_format.i_rate;
p_buffer->end_date = p_a52->last_date;
/* FIXME */
p_a52_adec->flags = A52_STEREO | A52_ADJUST_LEVEL;
/* Get the complete frame */
GetChunk( &p_a52_adec->bit_stream, p_a52_adec->p_frame_buffer + 7,
p_a52_adec->frame_size - 7 );
if( p_a52_adec->p_fifo->b_die ) return( -1 );
i_flags = A52_STEREO | A52_ADJUST_LEVEL;
/* do the actual decoding now */
vlc_mutex_lock( &a52_lock );
a52_frame( p_a52_adec->p_a52_state, p_a52_adec->p_frame_buffer,
&p_a52_adec->flags, &sample_level, 384 );
/* Do the actual decoding now */
a52_frame( p_a52->p_a52_state, p_frame_buffer,
&i_flags, &i_sample_level, 0 );
if( !p_a52_adec->b_dynrng )
a52_dynrng( p_a52_adec->p_a52_state, NULL, NULL );
if( !p_a52->b_dynrng )
{
a52_dynrng( p_a52->p_a52_state, NULL, NULL );
}
for( i = 0; i < 6; i++ )
for ( i = 0; i < 6; i++ )
{
if( a52_block( p_a52_adec->p_a52_state ) )
sample_t * p_samples;
if( a52_block( p_a52->p_a52_state ) )
{
msg_Warn( p_a52_adec->p_fifo, "a52_block failed for block %i", i );
msg_Warn( p_a52->p_fifo, "a52_block failed for block %i", i );
}
float2s16_2( a52_samples( p_a52_adec->p_a52_state ),
((int16_t *)p_buffer) + i * 256 * p_a52_adec->i_channels );
}
vlc_mutex_unlock( &a52_lock );
p_samples = a52_samples( p_a52->p_a52_state );
/* Interleave the *$% samples */
Interleave( (float *)(p_buffer->p_buffer + i * i_bytes_per_block),
p_samples, p_a52->output_format.i_channels );
}
vlc_mutex_lock( &p_a52_adec->p_aout_fifo->data_lock );
p_a52_adec->p_aout_fifo->i_end_frame =
(p_a52_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
vlc_cond_signal (&p_a52_adec->p_aout_fifo->data_wait);
vlc_mutex_unlock (&p_a52_adec->p_aout_fifo->data_lock);
aout_BufferPlay( p_a52->p_aout, p_a52->p_aout_input, p_buffer );
return 0;
}
......@@ -325,62 +314,14 @@ static int DecodeFrame( a52_adec_thread_t * p_a52_adec )
/*****************************************************************************
* EndThread : liba52 decoder thread destruction
*****************************************************************************/
static void EndThread (a52_adec_thread_t *p_a52_adec)
static void EndThread (a52_thread_t *p_a52)
{
/* If the audio output fifo was created, we destroy it */
if (p_a52_adec->p_aout_fifo != NULL)
if ( p_a52->p_aout_input != NULL )
{
aout_DestroyFifo (p_a52_adec->p_aout_fifo);
/* Make sure the output thread leaves the NextFrame() function */
vlc_mutex_lock (&(p_a52_adec->p_aout_fifo->data_lock));
vlc_cond_signal (&(p_a52_adec->p_aout_fifo->data_wait));
vlc_mutex_unlock (&(p_a52_adec->p_aout_fifo->data_lock));
aout_InputDelete( p_a52->p_aout, p_a52->p_aout_input );
}
vlc_mutex_lock( &a52_lock );
a52_free( p_a52_adec->p_a52_state );
vlc_mutex_unlock( &a52_lock );
free( p_a52_adec );
a52_free( p_a52->p_a52_state );
free( p_a52 );
}
/*****************************************************************************
* float2s16_2 : converts floats to ints using a trick based on the IEEE
* floating-point format
*****************************************************************************/
static inline int16_t convert (int32_t i)
{
if (i > 0x43c07fff)
return 32767;
else if (i < 0x43bf8000)
return -32768;
else
return i - 0x43c00000;
}
static void float2s16_2 (float * _f, int16_t * s16)
{
int i;
int32_t * f = (int32_t *) _f;
for (i = 0; i < 256; i++) {
s16[2*i] = convert (f[i]);
s16[2*i+1] = convert (f[i+256]);
}
}
/*****************************************************************************
* BitstreamCallback: Import parameters from the new data/PES packet
*****************************************************************************
* This function is called by input's NextDataPacket.
*****************************************************************************/
static void BitstreamCallback ( bit_stream_t * p_bit_stream,
vlc_bool_t b_new_pes )
{
if( b_new_pes )
{
/* Drop special A52 header */
/* p_bit_stream->p_byte += 3; */
}
}
......@@ -4,7 +4,7 @@
* (http://liba52.sf.net/).
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: a52.h,v 1.1 2002/08/04 17:23:42 sam Exp $
* $Id: a52.h,v 1.2 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -24,18 +24,14 @@
*****************************************************************************/
/*****************************************************************************
* a52_adec_thread_t : a52 decoder thread descriptor
* a52_thread_t : a52 decoder thread descriptor
*****************************************************************************/
typedef struct a52_adec_thread_s
typedef struct a52_thread_s
{
/*
* liba52 properties
*/
a52_state_t *p_a52_state;
int frame_size;
int flags;
int sample_rate;
int bit_rate;
a52_state_t * p_a52_state;
vlc_bool_t b_dynrng;
/* The bit stream structure handles the PES stream at the bit level */
......@@ -44,16 +40,14 @@ typedef struct a52_adec_thread_s
/*
* Input properties
*/
decoder_fifo_t *p_fifo; /* stores the PES stream data */
data_packet_t *p_data;
decoder_fifo_t * p_fifo; /* stores the PES stream data */
data_packet_t * p_data;
/*
* Output properties
*/
aout_fifo_t *p_aout_fifo; /* stores the decompressed audio frames */
int i_channels;
/* temporary buffer to store the raw frame to be decoded */
u8 p_frame_buffer[3840];
} a52_adec_thread_t;
aout_instance_t * p_aout; /* opaque */
aout_input_t * p_aout_input; /* opaque */
audio_sample_format_t output_format;
mtime_t last_date;
} a52_thread_t;
/*****************************************************************************
* aout.m: CoreAudio output plugin
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: aout.m,v 1.1 2002/08/04 17:23:43 sam Exp $
* Copyright (C) 2002 VideoLAN
* $Id: aout.m,v 1.2 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Colin Delacroix <colin@zoy.org>
* Jon Lech Johansen <jon-vl@nanocrew.net>
* Christophe Massiot <massiot@via.ecp.fr>
*
* 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
......@@ -26,9 +27,11 @@
* Preamble
*****************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include "aout_internal.h"
#include <Carbon/Carbon.h>
#include <CoreAudio/AudioHardware.h>
......@@ -44,31 +47,21 @@
struct aout_sys_t
{
AudioDeviceID device; // the audio device
AudioConverterRef s_converter; // the AudioConverter
int b_format; // format begun
AudioStreamBasicDescription s_src_stream_format;
AudioStreamBasicDescription s_dst_stream_format;
Ptr p_buffer; // ptr to the 32 bit float data
UInt32 ui_buffer_size; // audio device buffer size
vlc_bool_t b_buffer_data; // available buffer data?
vlc_mutex_t mutex_lock; // pthread locks for sync of
vlc_cond_t cond_sync; // Play and callback
mtime_t clock_diff; // diff between system clock & audio
AudioStreamBasicDescription stream_format;
UInt32 i_buffer_size; // audio device buffer size
mtime_t clock_diff;
};
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static int SetFormat ( aout_thread_t * );
static int GetBufInfo ( aout_thread_t *, int );
static void Play ( aout_thread_t *, byte_t *, int );
static int CABeginFormat ( aout_thread_t * );
static int CAEndFormat ( aout_thread_t * );
static int SetFormat ( aout_instance_t *p_aout );
static void Play ( aout_instance_t *p_aout,
aout_buffer_t *p_buffer );
static OSStatus CAIOCallback ( AudioDeviceID inDevice,
static OSStatus IOCallback ( AudioDeviceID inDevice,
const AudioTimeStamp *inNow,
const void *inInputData,
const AudioTimeStamp *inInputTime,
......@@ -77,189 +70,159 @@ static OSStatus CAIOCallback ( AudioDeviceID inDevice,
void *threadGlobals );
/*****************************************************************************
* OpenAudio: opens a CoreAudio HAL device
* Open: open a CoreAudio HAL device
*****************************************************************************/
int E_(OpenAudio) ( vlc_object_t *p_this )
int E_(OpenAudio)( vlc_object_t * p_this )
{
aout_thread_t * p_aout = (aout_thread_t *)p_this;
OSStatus err;
UInt32 ui_param_size;
/* allocate instance */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
UInt32 i_param_size;
aout_instance_t * p_aout = (aout_instance_t *)p_this;
struct aout_sys_t * p_sys;
/* Allocate instance */
p_sys = p_aout->output.p_sys = malloc( sizeof( struct aout_sys_t ) );
memset( p_sys, 0, sizeof( struct aout_sys_t ) );
if( p_aout->output.p_sys == NULL )
{
msg_Err( p_aout, "out of memory" );
return( 1 );
}
/* initialize members */
memset( p_aout->p_sys, 0, sizeof( aout_sys_t ) );
/* get the default output device */
ui_param_size = sizeof( p_aout->p_sys->device );
/* Get the default output device */
/* FIXME : be more clever in choosing from several devices */
i_param_size = sizeof( p_sys->device );
err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
&ui_param_size,
(void *)&p_aout->p_sys->device );
&i_param_size,
(void *)&p_sys->device );
if( err != noErr )
{
msg_Err( p_aout, "failed to get the device: %d", err );
return( -1 );
}
/* get the buffer size that the device uses for IO */
ui_param_size = sizeof( p_aout->p_sys->ui_buffer_size );
err = AudioDeviceGetProperty( p_aout->p_sys->device, 0, false,
kAudioDevicePropertyBufferSize,
&ui_param_size,
&p_aout->p_sys->ui_buffer_size );
p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
if( err != noErr )
{
msg_Err( p_aout, "failed to get device buffer size: %d", err );
return( -1 );
}
return 0;
}
/* get a description of the data format used by the device */
ui_param_size = sizeof( p_aout->p_sys->s_dst_stream_format );
err = AudioDeviceGetProperty( p_aout->p_sys->device, 0, false,
kAudioDevicePropertyStreamFormat,
&ui_param_size,
&p_aout->p_sys->s_dst_stream_format );
/*****************************************************************************
* SetFormat: find the closest available format from p_format
*****************************************************************************/
static int SetFormat( aout_instance_t * p_aout )
{
struct aout_sys_t * p_sys = p_aout->output.p_sys;
OSErr err;
/* Get a description of the data format used by the device */
UInt32 i_param_size = sizeof( p_sys->stream_format );
err = AudioDeviceGetProperty( p_sys->device, 0, false,
kAudioDevicePropertyStreamFormat,
&i_param_size,
&p_sys->stream_format );
if( err != noErr )
{
msg_Err( p_aout, "failed to get dst stream format: %d", err );
return( -1 );
msg_Err( p_aout, "failed to get stream format: %d", err );
return -1 ;
}
if( p_aout->p_sys->s_dst_stream_format.mFormatID != kAudioFormatLinearPCM )
if( p_sys->stream_format.mFormatID != kAudioFormatLinearPCM )
{
msg_Err( p_aout, "kAudioFormatLinearPCM required" );
return( -1 );
return -1 ;
}
/* initialize mutex and cond */
vlc_mutex_init( p_aout, &p_aout->p_sys->mutex_lock );
vlc_cond_init( p_aout, &p_aout->p_sys->cond_sync );
/* initialize source stream format */
memcpy( &p_aout->p_sys->s_src_stream_format,
&p_aout->p_sys->s_dst_stream_format,
sizeof( p_aout->p_sys->s_src_stream_format ) );
if( CABeginFormat( p_aout ) )
/* We only deal with floats */
if ( p_aout->output.output.i_format != AOUT_FMT_FLOAT32 )
{
msg_Err( p_aout, "CABeginFormat failed" );
return( -1 );
msg_Err( p_aout, "cannot set format 0x%x",
p_aout->output.output.i_format );
return -1;
}
p_aout->pf_setformat = SetFormat;
p_aout->pf_getbufinfo = GetBufInfo;
p_aout->pf_play = Play;
return( 0 );
}
/*****************************************************************************
* SetFormat: pretends to set the dsp output format
*****************************************************************************/
static int SetFormat( aout_thread_t *p_aout )
{
if( CAEndFormat( p_aout ) )
p_sys->stream_format.mFormatFlags |=
kLinearPCMFormatFlagIsFloat;
/* Set sample rate and channels per frame */
p_sys->stream_format.mSampleRate
= p_aout->output.output.i_rate;
p_sys->stream_format.mChannelsPerFrame
= p_aout->output.output.i_channels;
/* Get the buffer size that the device uses for IO */
i_param_size = sizeof( p_sys->i_buffer_size );
#if 0
err = AudioDeviceGetProperty( p_sys->device, 0, false,
kAudioDevicePropertyBufferSize,
&i_param_size, &p_sys->i_buffer_size );
msg_Dbg( p_aout, "toto : %d", p_sys->i_buffer_size );
#else
p_sys->i_buffer_size = sizeof(float) * p_aout->output.output.i_channels
* 1536;
err = AudioDeviceSetProperty( p_sys->device, 0, 0, false,
kAudioDevicePropertyBufferSize,
i_param_size, &p_sys->i_buffer_size );
#endif
if( err != noErr )
{
msg_Err( p_aout, "CAEndFormat failed" );
msg_Err( p_aout, "failed to set device buffer size: %d", err );
return( -1 );
}
switch( p_aout->i_format )
{
case AOUT_FMT_S8:
msg_Err( p_aout,
"Signed 8 not supported yet, please report stream" );
return( -1 );
p_aout->output.i_nb_samples = p_sys->i_buffer_size / sizeof(float)
/ p_aout->output.output.i_channels;
case AOUT_FMT_U8:
msg_Err( p_aout,
"Unsigned 8 not supported yet, please report stream" );
return( -1 );
/* Add callback */
err = AudioDeviceAddIOProc( p_sys->device,
(AudioDeviceIOProc)IOCallback,
(void *)p_aout );
case AOUT_FMT_S16_LE:
p_aout->p_sys->s_src_stream_format.mFormatFlags &=
~kLinearPCMFormatFlagIsBigEndian;
p_aout->p_sys->s_src_stream_format.mFormatFlags |=
kLinearPCMFormatFlagIsSignedInteger;
break;
case AOUT_FMT_S16_BE:
p_aout->p_sys->s_src_stream_format.mFormatFlags |=
kLinearPCMFormatFlagIsBigEndian;
p_aout->p_sys->s_src_stream_format.mFormatFlags |=
kLinearPCMFormatFlagIsSignedInteger;
break;
case AOUT_FMT_U16_LE:
p_aout->p_sys->s_src_stream_format.mFormatFlags &=
~kLinearPCMFormatFlagIsBigEndian;
p_aout->p_sys->s_src_stream_format.mFormatFlags &=
~kLinearPCMFormatFlagIsSignedInteger;
break;
case AOUT_FMT_U16_BE:
p_aout->p_sys->s_src_stream_format.mFormatFlags |=
kLinearPCMFormatFlagIsBigEndian;
p_aout->p_sys->s_src_stream_format.mFormatFlags &=
~kLinearPCMFormatFlagIsSignedInteger;
break;
default:
msg_Err( p_aout, "audio format (0x%08x) not supported now,"
"please report stream", p_aout->i_format );
return( -1 );
/* Open the output with callback IOCallback */
err = AudioDeviceStart( p_sys->device,
(AudioDeviceIOProc)IOCallback );
if( err != noErr )
{
msg_Err( p_aout, "AudioDeviceStart failed: %d", err );
return -1;
}
/* source format is not float */
p_aout->p_sys->s_src_stream_format.mFormatFlags &=
~kLinearPCMFormatFlagIsFloat;
/* Let's pray for the following operation to be atomic... */
p_sys->clock_diff = mdate()
- AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()) / 1000;
/* if destination format is float, take size diff into account */
if( p_aout->p_sys->s_dst_stream_format.mFormatFlags &
kLinearPCMFormatFlagIsFloat )
{
p_aout->p_sys->s_src_stream_format.mBytesPerPacket =
p_aout->p_sys->s_dst_stream_format.mBytesPerPacket / 2;
p_aout->p_sys->s_src_stream_format.mBytesPerFrame =
p_aout->p_sys->s_src_stream_format.mBytesPerFrame / 2;
p_aout->p_sys->s_src_stream_format.mBitsPerChannel =
p_aout->p_sys->s_src_stream_format.mBitsPerChannel / 2;
}
return 0;
}
/* set sample rate and channels per frame */
p_aout->p_sys->s_src_stream_format.mSampleRate = p_aout->i_rate;
p_aout->p_sys->s_src_stream_format.mChannelsPerFrame = p_aout->i_channels;
/*****************************************************************************
* Close: close the CoreAudio HAL device
*****************************************************************************/
void E_(CloseAudio)( aout_instance_t * p_aout )
{
struct aout_sys_t * p_sys = p_aout->output.p_sys;
OSStatus err;
if( CABeginFormat( p_aout ) )
/* Stop playing sound through the device */
err = AudioDeviceStop( p_sys->device,
(AudioDeviceIOProc)IOCallback );
if( err != noErr )
{
msg_Err( p_aout, "CABeginFormat failed" );
return( -1 );
msg_Err( p_aout, "AudioDeviceStop failed: %d", err );
}
return( 0 );
free( p_sys );
}
/*****************************************************************************
* GetBufInfo: returns available bytes in buffer
* Play: queue a buffer for playing by IOCallback
*****************************************************************************/
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
static void Play( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
{
return( 0 ); /* send data as soon as possible */
aout_FifoPush( p_aout, &p_aout->output.fifo, p_buffer );
}
/*****************************************************************************
* CAIOCallback : callback for audio output
* IOCallback : callback for audio output
*****************************************************************************/
static OSStatus CAIOCallback( AudioDeviceID inDevice,
static OSStatus IOCallback( AudioDeviceID inDevice,
const AudioTimeStamp *inNow,
const void *inInputData,
const AudioTimeStamp *inInputTime,
......@@ -267,225 +230,32 @@ static OSStatus CAIOCallback( AudioDeviceID inDevice,
const AudioTimeStamp *inOutputTime,
void *threadGlobals )
{
aout_thread_t *p_aout = (aout_thread_t *)threadGlobals;
aout_sys_t *p_sys = p_aout->p_sys;
aout_instance_t * p_aout = (aout_instance_t *)threadGlobals;
struct aout_sys_t * p_sys = p_aout->output.p_sys;
mtime_t current_date;
AudioTimeStamp host_time;
aout_buffer_t * p_buffer;
host_time.mFlags = kAudioTimeStampHostTimeValid;
AudioDeviceTranslateTime( inDevice, inOutputTime, &host_time );
//intf_Msg( "%lld", AudioConvertHostTimeToNanos(host_time.mHostTime) / 1000 + p_aout->p_sys->clock_diff - p_aout->date );
p_aout->date = p_aout->p_sys->clock_diff + AudioConvertHostTimeToNanos(host_time.mHostTime) / 1000;
current_date = p_sys->clock_diff
+ AudioConvertHostTimeToNanos(host_time.mHostTime) / 1000;
p_buffer = aout_OutputNextBuffer( p_aout, current_date );
/* move data into output data buffer */
if( p_sys->b_buffer_data )
if ( p_buffer != NULL )
{
BlockMoveData( p_sys->p_buffer,
BlockMoveData( p_buffer->p_buffer,
outOutputData->mBuffers[ 0 ].mData,
p_sys->ui_buffer_size );
p_sys->i_buffer_size );
aout_BufferFree( p_buffer );
}
else
{
memset(outOutputData->mBuffers[ 0 ].mData, 0, p_sys->ui_buffer_size);
//X msg_Warn( p_aout, "audio output is starving, expect glitches" );
}
/* see Play below */
vlc_mutex_lock( &p_sys->mutex_lock );
p_sys->b_buffer_data = 0;
vlc_cond_signal( &p_sys->cond_sync );
vlc_mutex_unlock( &p_sys->mutex_lock );
return( noErr );
}
/*****************************************************************************
* Play: play a sound
*****************************************************************************/
static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
{
OSStatus err;
UInt32 ui_buffer_size = p_aout->p_sys->ui_buffer_size;
/*
* wait for a callback to occur (to flush the buffer), so Play
* can't be called twice, losing the data we just wrote.
*/
vlc_mutex_lock( &p_aout->p_sys->mutex_lock );
if ( p_aout->p_sys->b_buffer_data )
{
vlc_cond_wait( &p_aout->p_sys->cond_sync, &p_aout->p_sys->mutex_lock );
}
vlc_mutex_unlock( &p_aout->p_sys->mutex_lock );
err = AudioConverterConvertBuffer( p_aout->p_sys->s_converter,
i_size, buffer,
&ui_buffer_size,
p_aout->p_sys->p_buffer );
if( err != noErr )
{
msg_Err( p_aout, "ConvertBuffer failed: %d", err );
}
else
{
p_aout->p_sys->b_buffer_data = 1;
}
}
/*****************************************************************************
* CloseAudio: closes the CoreAudio HAL device
*****************************************************************************/
void E_(CloseAudio) ( vlc_object_t *p_this )
{
aout_thread_t * p_aout = (aout_thread_t *)p_this;
if( CAEndFormat( p_aout ) )
{
msg_Err( p_aout, "CAEndFormat failed" );
memset(outOutputData->mBuffers[ 0 ].mData, 0, p_sys->i_buffer_size);
}
/* destroy lock and cond */
vlc_mutex_destroy( &p_aout->p_sys->mutex_lock );
vlc_cond_destroy( &p_aout->p_sys->cond_sync );
free( p_aout->p_sys );
return noErr;
}
/*****************************************************************************
* CABeginFormat: creates an AudioConverter
*****************************************************************************/
static int CABeginFormat( aout_thread_t *p_aout )
{
OSStatus err;
UInt32 ui_param_size;
if( p_aout->p_sys->b_format )
{
msg_Err( p_aout, "CABeginFormat (b_format)" );
return( 1 );
}
p_aout->p_sys->ui_buffer_size = 2 * 2 * sizeof(s16) *
((s64)p_aout->i_rate * AOUT_BUFFER_DURATION) / 1000000;
/* set the buffer size that the device uses for IO */
ui_param_size = sizeof( p_aout->p_sys->ui_buffer_size );
err = AudioDeviceSetProperty( p_aout->p_sys->device, 0, 0, false,
kAudioDevicePropertyBufferSize,
ui_param_size,
&p_aout->p_sys->ui_buffer_size );
//p_aout->i_latency = p_aout->p_sys->ui_buffer_size / 2;
if( err != noErr )
{
msg_Err( p_aout, "AudioDeviceSetProperty failed: %d", err );
return( 1 );
}
/* allocate audio buffer */
p_aout->p_sys->p_buffer = NewPtrClear( p_aout->p_sys->ui_buffer_size );
if( p_aout->p_sys->p_buffer == nil )
{
msg_Err( p_aout, "failed to allocate audio buffer" );
return( 1 );
}
/* create a new AudioConverter */
err = AudioConverterNew( &p_aout->p_sys->s_src_stream_format,
&p_aout->p_sys->s_dst_stream_format,
&p_aout->p_sys->s_converter );
if( err != noErr )
{
msg_Err( p_aout, "AudioConverterNew failed: %d", err );
DisposePtr( p_aout->p_sys->p_buffer );
return( 1 );
}
/* add callback */
err = AudioDeviceAddIOProc( p_aout->p_sys->device,
(AudioDeviceIOProc)CAIOCallback,
(void *)p_aout );
if( err != noErr )
{
msg_Err( p_aout, "AudioDeviceAddIOProc failed: %d", err );
AudioConverterDispose( p_aout->p_sys->s_converter );
DisposePtr( p_aout->p_sys->p_buffer );
return( 1 );
}
/* open the output */
err = AudioDeviceStart( p_aout->p_sys->device,
(AudioDeviceIOProc)CAIOCallback );
if( err != noErr )
{
msg_Err( p_aout, "AudioDeviceStart failed: %d", err );
AudioConverterDispose( p_aout->p_sys->s_converter );
DisposePtr( p_aout->p_sys->p_buffer );
return( 1 );
}
/* Let's pray for the following operation to be atomic... */
p_aout->p_sys->clock_diff = mdate()
- AudioConvertHostTimeToNanos(AudioGetCurrentHostTime()) / 1000
+ (mtime_t)p_aout->p_sys->ui_buffer_size / 4 * 1000000 / (mtime_t)p_aout->i_rate
+ p_aout->p_vlc->i_desync;
p_aout->p_sys->b_format = 1;
return( 0 );
}
/*****************************************************************************
* CAEndFormat: destroys the AudioConverter
*****************************************************************************/
static int CAEndFormat( aout_thread_t *p_aout )
{
OSStatus err;
if( !p_aout->p_sys->b_format )
{
msg_Err( p_aout, "CAEndFormat (!b_format)" );
return( 1 );
}
/* stop playing sound through the device */
err = AudioDeviceStop( p_aout->p_sys->device,
(AudioDeviceIOProc)CAIOCallback );
if( err != noErr )
{
msg_Err( p_aout, "AudioDeviceStop failed: %d", err );
return( 1 );
}
/* remove the callback */
err = AudioDeviceRemoveIOProc( p_aout->p_sys->device,
(AudioDeviceIOProc)CAIOCallback );
if( err != noErr )
{
msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: %d", err );
return( 1 );
}
/* destroy the AudioConverter */
err = AudioConverterDispose( p_aout->p_sys->s_converter );
if( err != noErr )
{
msg_Err( p_aout, "AudioConverterDispose failed: %d", err );
return( 1 );
}
/* release audio buffer */
DisposePtr( p_aout->p_sys->p_buffer );
p_aout->p_sys->b_format = 0;
return( 0 );
}
......@@ -2,7 +2,7 @@
* vout.m: MacOS X video output plugin
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: vout.m,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: vout.m,v 1.2 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Colin Delacroix <colin@zoy.org>
* Florian G. Pflug <fgp@phlo.org>
......@@ -58,7 +58,6 @@ struct picture_sys_t
static int vout_Init ( vout_thread_t * );
static void vout_End ( vout_thread_t * );
static int vout_Manage ( vout_thread_t * );
static void vout_Render ( vout_thread_t *, picture_t * );
static void vout_Display ( vout_thread_t *, picture_t * );
static int CoSendRequest ( vout_thread_t *, long );
......@@ -719,6 +718,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
switch( key )
{
#if 0
case (unichar)0xf700: /* up-arrow */
{
aout_thread_t * p_aout = vlc_object_find( p_vout, VLC_OBJECT_AOUT,
......@@ -750,6 +750,7 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
}
}
break;
#endif
case 'f': case 'F':
[self toggleFullscreen];
......
/*****************************************************************************
* aout_dummy.c : dummy audio output plugin
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: aout.c,v 1.1 2002/08/04 17:23:43 sam Exp $
* Copyright (C) 2002 VideoLAN
* $Id: aout.c,v 1.2 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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
......@@ -25,52 +25,46 @@
* Preamble
*****************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include "aout_internal.h"
/*****************************************************************************
* Local prototypes.
*****************************************************************************/
static int SetFormat ( aout_thread_t * );
static int GetBufInfo ( aout_thread_t *, int );
static void Play ( aout_thread_t *, byte_t *, int );
static int SetFormat ( aout_instance_t * );
static void Play ( aout_instance_t *, aout_buffer_t * );
/*****************************************************************************
* OpenAudio: opens a dummy audio device
* OpenAudio: open a dummy audio device
*****************************************************************************/
int E_(OpenAudio) ( vlc_object_t *p_this )
int E_(OpenAudio) ( vlc_object_t * p_this )
{
aout_thread_t * p_aout = (aout_thread_t *)p_this;
aout_instance_t * p_aout = (aout_instance_t *)p_this;
p_aout->pf_setformat = SetFormat;
p_aout->pf_getbufinfo = GetBufInfo;
p_aout->pf_play = Play;
p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
return VLC_SUCCESS;
}
/*****************************************************************************
* SetFormat: pretends to set the dsp output format
*****************************************************************************/
static int SetFormat( aout_thread_t *p_aout )
{
return( 0 );
}
/*****************************************************************************
* GetBufInfo: returns available bytes in buffer
* SetFormat: pretend to set the dsp output format
*****************************************************************************/
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
static int SetFormat( aout_instance_t * p_aout )
{
return( sizeof(s16) * i_buffer_limit + 1 ); /* value big enough to sleep */
p_aout->output.i_nb_samples = 2048;
return 0;
}
/*****************************************************************************
* Play: pretends to play a sound
* Play: pretend to play a sound
*****************************************************************************/
static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
static void Play( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
{
;
aout_BufferFree( p_buffer );
}
......@@ -2,7 +2,7 @@
* dummy.c : dummy plugin for vlc
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: dummy.c,v 1.1 2002/08/04 17:23:43 sam Exp $
* $Id: dummy.c,v 1.2 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -56,10 +56,10 @@ vlc_module_begin();
set_capability( "decoder", 0 );
set_callbacks( E_(OpenDecoder), NULL );
add_submodule();
set_capability( "audio output", 0 );
set_capability( "audio output", 1 );
set_callbacks( E_(OpenAudio), NULL );
add_submodule();
set_capability( "video output", 0 );
set_capability( "video output", 1 );
set_callbacks( E_(OpenVideo), NULL );
add_category_hint( N_("Video"), NULL );
add_string( "dummy-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT );
......
......@@ -2,7 +2,7 @@
* aout_sdl.c : audio sdl functions library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: aout.c,v 1.1 2002/08/04 17:23:44 sam Exp $
* $Id: aout.c,v 1.2 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -34,65 +34,32 @@
#include <vlc/vlc.h>
#include <vlc/aout.h>
#include "aout_internal.h"
#include SDL_INCLUDE_FILE
/*****************************************************************************
* 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
struct aout_sys_t
{
byte_t * audio_buf;
int i_audio_end;
vlc_bool_t b_active;
};
#define DEFAULT_FRAME_SIZE 2048
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int SetFormat ( aout_thread_t * );
static int GetBufInfo ( aout_thread_t *, int );
static void Play ( aout_thread_t *, byte_t *, int );
static int SetFormat ( aout_instance_t * );
static void Play ( aout_instance_t *, aout_buffer_t * );
static void SDLCallback ( void *, Uint8 *, int );
/*****************************************************************************
* OpenAudio: open the audio device
*****************************************************************************
* 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.
*****************************************************************************/
int E_(OpenAudio) ( vlc_object_t *p_this )
int E_(OpenAudio) ( aout_instance_t *p_aout )
{
aout_thread_t * p_aout = (aout_thread_t *)p_this;
SDL_AudioSpec desired;
if( SDL_WasInit( SDL_INIT_AUDIO ) != 0 )
{
return( 1 );
}
p_aout->pf_setformat = SetFormat;
p_aout->pf_getbufinfo = GetBufInfo;
p_aout->pf_play = Play;
/* Allocate structure */
p_aout->p_sys = malloc( sizeof( aout_sys_t ) );
if( p_aout->p_sys == NULL )
{
msg_Err( p_aout, "out of memory" );
return( 1 );
}
p_aout->output.pf_setformat = SetFormat;
p_aout->output.pf_play = Play;
/* Initialize library */
if( SDL_Init( SDL_INIT_AUDIO
......@@ -108,121 +75,49 @@ int E_(OpenAudio) ( vlc_object_t *p_this )
) < 0 )
{
msg_Err( p_aout, "cannot initialize SDL (%s)", SDL_GetError() );
free( p_aout->p_sys );
return( 1 );
}
p_aout->p_sys->i_audio_end = 0;
p_aout->p_sys->audio_buf = malloc( OVERFLOWLIMIT );
/* Initialize some variables */
/* TODO: write conversion beetween AOUT_FORMAT_DEFAULT
* AND AUDIO* from SDL. */
desired.freq = p_aout->i_rate;
#ifdef WORDS_BIGENDIAN
desired.format = AUDIO_S16MSB; /* stereo 16 bits */
#else
desired.format = AUDIO_S16LSB; /* stereo 16 bits */
#endif
desired.channels = p_aout->i_channels;
desired.callback = SDLCallback;
desired.userdata = p_aout->p_sys;
desired.samples = 1024;
/* 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 )
{
msg_Err( p_aout, "SDL_OpenAudio failed (%s)", SDL_GetError() );
SDL_QuitSubSystem( SDL_INIT_AUDIO );
free( p_aout->p_sys );
return( -1 );
}
p_aout->p_sys->b_active = 1;
SDL_PauseAudio( 0 );
return( 0 );
}
/*****************************************************************************
* SetFormat: reset the audio device and sets its format
*****************************************************************************
* This functions resets the audio 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 SetFormat( aout_thread_t *p_aout )
static int SetFormat( aout_instance_t *p_aout )
{
/* TODO: finish and clean this */
SDL_AudioSpec desired;
/*i_format = p_aout->i_format;*/
desired.freq = p_aout->i_rate; /* Set the output rate */
#ifdef WORDS_BIGENDIAN
desired.format = AUDIO_S16MSB; /* stereo 16 bits */
#else
desired.format = AUDIO_S16LSB; /* stereo 16 bits */
#endif
desired.channels = p_aout->i_channels;
desired.freq = p_aout->output.output.i_rate;
desired.format = AUDIO_S16SYS;
desired.channels = p_aout->output.output.i_channels;
desired.callback = SDLCallback;
desired.userdata = p_aout->p_sys;
desired.samples = 2048;
/* Open the sound device */
SDL_PauseAudio( 1 );
SDL_CloseAudio();
desired.userdata = p_aout;
desired.samples = DEFAULT_FRAME_SIZE;
/* Open the sound device - FIXME : get the "natural" paramaters */
if( SDL_OpenAudio( &desired, NULL ) < 0 )
{
p_aout->p_sys->b_active = 0;
return( -1 );
return -1;
}
p_aout->p_sys->b_active = 1;
p_aout->output.output.i_format = AOUT_FMT_S16_NE;
p_aout->output.i_nb_samples = DEFAULT_FRAME_SIZE;
SDL_PauseAudio( 0 );
return( 0 );
}
/*****************************************************************************
* GetBufInfo: buffer status query
*****************************************************************************
* returns the number of bytes in the audio buffer compared to the size of
* i_buffer_limit...
*****************************************************************************/
static int GetBufInfo( aout_thread_t *p_aout, int i_buffer_limit )
{
if(i_buffer_limit > p_aout->p_sys->i_audio_end)
{
/* returning 0 here juste gives awful sound in the speakers :/ */
return( i_buffer_limit );
}
return( p_aout->p_sys->i_audio_end - i_buffer_limit);
return 0;
}
/*****************************************************************************
* Play: play a sound samples buffer
*****************************************************************************
* This function writes a buffer of i_length bytes in the dsp
*****************************************************************************/
static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
static void Play( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
{
byte_t * audio_buf = p_aout->p_sys->audio_buf;
SDL_LockAudio(); /* Stop callbacking */
p_aout->p_sys->audio_buf = realloc( audio_buf,
p_aout->p_sys->i_audio_end + i_size);
memcpy( p_aout->p_sys->audio_buf + p_aout->p_sys->i_audio_end,
buffer, i_size);
p_aout->p_sys->i_audio_end += i_size;
aout_FifoPush( p_aout, &p_aout->output.fifo, p_buffer );
SDL_UnlockAudio(); /* go on callbacking */
}
......@@ -230,51 +125,38 @@ static void Play( aout_thread_t *p_aout, byte_t *buffer, int i_size )
/*****************************************************************************
* CloseAudio: close the audio device
*****************************************************************************/
void E_(CloseAudio) ( vlc_object_t *p_this )
void E_(CloseAudio) ( aout_instance_t *p_aout )
{
aout_thread_t * p_aout = (aout_thread_t *)p_this;
if( p_aout->p_sys->b_active )
{
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 );
}
}
SDL_PauseAudio( 1 );
SDL_CloseAudio();
SDL_QuitSubSystem( SDL_INIT_AUDIO );
free( p_aout->p_sys ); /* Close the Output. */
}
/*****************************************************************************
* SDLCallback: what to do once SDL has played sound samples
*****************************************************************************/
static void SDLCallback( void *userdata, byte_t *stream, int len )
static void SDLCallback( void * _p_aout, byte_t * p_stream, int i_len )
{
aout_sys_t * p_sys = userdata;
aout_instance_t * p_aout = (aout_instance_t *)_p_aout;
/* FIXME : take into account SDL latency instead of mdate() */
aout_buffer_t * p_buffer = aout_OutputNextBuffer( p_aout, mdate() );
if( p_sys->i_audio_end > OVERFLOWLIMIT )
if ( i_len != DEFAULT_FRAME_SIZE * sizeof(s16)
* p_aout->output.output.i_channels )
{
//X msg_Err( p_aout, "aout_SDLCallback overflowed" );
free( p_sys->audio_buf );
p_sys->audio_buf = NULL;
p_sys->i_audio_end = 0;
/* we've gone to slow, increase output freq */
msg_Err( p_aout, "SDL doesn't know its buffer size (%d)", i_len );
}
/* if we are not in underrun */
if( p_sys->i_audio_end > len )
if ( p_buffer != NULL )
{
p_aout->p_vlc->pf_memcpy( p_stream, p_buffer->p_buffer, i_len );
aout_BufferFree( p_buffer );
}
else
{
p_sys->i_audio_end -= len;
memcpy( stream, p_sys->audio_buf, len );
memmove( p_sys->audio_buf, p_sys->audio_buf + len, p_sys->i_audio_end );
memset( p_stream, 0, i_len );
}
}
/*****************************************************************************
* aout_ext-dec.c : exported fifo management functions
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: aout_ext-dec.c,v 1.18 2002/06/02 09:03:54 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
*
* 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 <stdlib.h> /* calloc(), malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#include "audio_output.h"
/*****************************************************************************
* aout_CreateFifo
*****************************************************************************/
aout_fifo_t * __aout_CreateFifo( vlc_object_t *p_this, int i_format,
int i_channels, int i_rate, int i_frame_size,
void *p_buffer )
{
aout_thread_t *p_aout;
aout_fifo_t *p_fifo = NULL;
int i_index;
/* Spawn an audio output if there is none */
p_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT, FIND_ANYWHERE );
if( p_aout )
{
if( p_aout->fifo[0].i_format != i_format )
{
msg_Dbg( p_this, "changing aout type" );
vlc_object_detach_all( p_aout );
vlc_object_release( p_aout );
aout_DestroyThread( p_aout );
p_aout = NULL;
}
}
if( p_aout == NULL )
{
msg_Dbg( p_this, "no aout present, spawning one" );
p_aout = aout_CreateThread( p_this, i_channels, i_rate );
/* Everything failed */
if( p_aout == NULL )
{
return NULL;
}
}
/* temporary hack to switch output type (mainly for spdif)
* FIXME: to be adapted when several output are available */
/* Take the fifos lock */
vlc_mutex_lock( &p_aout->fifos_lock );
/* Look for a free fifo structure */
for( i_index = 0; i_index < AOUT_MAX_FIFOS; i_index++ )
{
if( p_aout->fifo[i_index].i_format == AOUT_FIFO_NONE )
{
p_fifo = &p_aout->fifo[i_index];
p_fifo->i_fifo = i_index;
break;
}
}
if( p_fifo == NULL )
{
msg_Err( p_aout, "no fifo available" );
vlc_mutex_unlock( &p_aout->fifos_lock );
return NULL;
}
/* Initialize the new fifo structure */
switch ( p_fifo->i_format = i_format )
{
case AOUT_FIFO_PCM:
case AOUT_FIFO_SPDIF:
p_fifo->b_die = 0;
p_fifo->i_channels = i_channels;
p_fifo->i_rate = i_rate;
p_fifo->i_frame_size = i_frame_size;
p_fifo->i_unit_limit = (AOUT_FIFO_SIZE + 1)
* (i_frame_size / i_channels);
/* Allocate the memory needed to store the audio frames and their
* dates. As the fifo is a rotative fifo, we must be able to find
* out whether the fifo is full or empty, that's why we must in
* fact allocate memory for (AOUT_FIFO_SIZE+1) audio frames. */
p_fifo->date = malloc( ( sizeof(s16) * i_frame_size
+ sizeof(mtime_t) )
* ( AOUT_FIFO_SIZE + 1 ) );
if ( p_fifo->date == NULL )
{
msg_Err( p_aout, "out of memory" );
p_fifo->i_format = AOUT_FIFO_NONE;
vlc_mutex_unlock( &p_aout->fifos_lock );
return NULL;
}
p_fifo->buffer = (u8 *)p_fifo->date + sizeof(mtime_t)
* ( AOUT_FIFO_SIZE + 1 );
/* Set the fifo's buffer as empty (the first frame that is to be
* played is also the first frame that is not to be played) */
p_fifo->i_start_frame = 0;
/* p_fifo->i_next_frame = 0; */
p_fifo->i_end_frame = 0;
/* Waiting for the audio decoder to compute enough frames to work
* out the fifo's current rate (as soon as the decoder has decoded
* enough frames, the members of the fifo structure that are not
* initialized now will be calculated) */
p_fifo->b_start_frame = 0;
p_fifo->b_next_frame = 0;
break;
default:
msg_Err( p_aout, "unknown fifo type 0x%x", p_fifo->i_format );
p_fifo->i_format = AOUT_FIFO_NONE;
vlc_mutex_unlock( &p_aout->fifos_lock );
return NULL;
}
/* Release the fifos lock */
vlc_mutex_unlock( &p_aout->fifos_lock );
msg_Dbg( p_aout, "fifo #%i allocated, %i channels, rate %li, "
"frame size %i", p_fifo->i_fifo, p_fifo->i_channels,
p_fifo->i_rate, p_fifo->i_frame_size );
/* Return the pointer to the fifo structure */
return p_fifo;
}
/*****************************************************************************
* aout_DestroyFifo
*****************************************************************************/
void aout_DestroyFifo( aout_fifo_t * p_fifo )
{
//X intf_Warn( p_fifo, 2, "fifo #%i destroyed", p_fifo->i_fifo );
vlc_mutex_lock( &p_fifo->data_lock );
p_fifo->b_die = 1;
vlc_mutex_unlock( &p_fifo->data_lock );
}
/*****************************************************************************
* aout_FreeFifo
*****************************************************************************/
void aout_FreeFifo( aout_fifo_t * p_fifo )
{
switch ( p_fifo->i_format )
{
case AOUT_FIFO_NONE:
break;
case AOUT_FIFO_PCM:
case AOUT_FIFO_SPDIF:
free( p_fifo->date );
p_fifo->i_format = AOUT_FIFO_NONE;
break;
default:
break;
}
}
/*****************************************************************************
* aout_pcm.c: PCM audio output functions
*****************************************************************************
* Copyright (C) 1999-2002 VideoLAN
* $Id: aout_pcm.c,v 1.8 2002/06/01 12:32:01 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
*
* 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 <stdlib.h> /* calloc(), malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#include "audio_output.h"
#include "aout_pcm.h"
/* Biggest difference allowed between scheduled playing date and actual date
(in microseconds) */
#define MAX_DELTA 50000
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void FillBuffer( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
static int NextFrame ( aout_thread_t * p_aout, aout_fifo_t * p_fifo,
mtime_t aout_date );
/*****************************************************************************
* Functions
*****************************************************************************/
void aout_PCMThread( aout_thread_t * p_aout )
{
int i_fifo;
int i_buffer, i_buffer_limit, i_units = 0;
#if defined(WIN32)
if( !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL) )
msg_Warn( p_aout, "could not change priority of aout_PCMThread()" );
#endif
/* As the s32_buffer was created with calloc(), we don't have to set this
* memory to zero and we can immediately jump into the thread's loop */
while ( ! p_aout->b_die )
{
vlc_mutex_lock( &p_aout->fifos_lock );
for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
{
if( p_aout->fifo[i_fifo].b_die )
{
aout_FreeFifo( &p_aout->fifo[i_fifo] );
}
else
{
FillBuffer( p_aout, &p_aout->fifo[i_fifo] );
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
i_buffer_limit = p_aout->i_units * p_aout->i_channels;
switch ( p_aout->i_format )
{
case AOUT_FMT_U8:
for ( i_buffer = 0; i_buffer < i_buffer_limit; i_buffer++ )
{
((u8*)p_aout->buffer)[i_buffer] = (u8)(
(p_aout->s32_buffer[i_buffer] / AOUT_MAX_FIFOS / 256 + 128)
* p_aout->i_volume / 256);
p_aout->s32_buffer[i_buffer] = 0;
}
break;
case AOUT_FMT_S8:
for ( i_buffer = 0; i_buffer < i_buffer_limit; i_buffer++ )
{
((s8*)p_aout->buffer)[i_buffer] = (s8)(
p_aout->s32_buffer[i_buffer] / AOUT_MAX_FIFOS / 256
* p_aout->i_volume / 256);
p_aout->s32_buffer[i_buffer] = 0;
}
break;
case AOUT_FMT_U16_LE:
case AOUT_FMT_U16_BE:
for ( i_buffer = 0; i_buffer < i_buffer_limit; i_buffer++ )
{
((u16*)p_aout->buffer)[i_buffer] = (u16)(
(p_aout->s32_buffer[i_buffer] / AOUT_MAX_FIFOS + 128)
* p_aout->i_volume / 256);
p_aout->s32_buffer[i_buffer] = 0;
}
break;
case AOUT_FMT_S16_LE:
case AOUT_FMT_S16_BE:
for ( i_buffer = 0; i_buffer < i_buffer_limit; i_buffer++ )
{
((s16*)p_aout->buffer)[i_buffer] = (s16)(
p_aout->s32_buffer[i_buffer] / AOUT_MAX_FIFOS
* p_aout->i_volume / 256);
p_aout->s32_buffer[i_buffer] = 0;
}
break;
}
switch ( p_aout->i_format )
{
case AOUT_FMT_U8:
case AOUT_FMT_S8:
i_units = p_aout->pf_getbufinfo( p_aout, i_buffer_limit );
p_aout->date = mdate() + ((((mtime_t)((i_units +
p_aout->i_latency) / p_aout->i_channels)) * 1000000) /
((mtime_t)p_aout->i_rate)) + p_aout->p_vlc->i_desync;
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer,
i_buffer_limit );
break;
case AOUT_FMT_U16_LE:
case AOUT_FMT_U16_BE:
case AOUT_FMT_S16_LE:
case AOUT_FMT_S16_BE:
i_units = p_aout->pf_getbufinfo( p_aout, i_buffer_limit * 2 ) / 2;
p_aout->date = mdate() + ((((mtime_t)((i_units +
p_aout->i_latency / 2) / p_aout->i_channels)) * 1000000) /
((mtime_t)p_aout->i_rate)) + p_aout->p_vlc->i_desync;
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer,
i_buffer_limit * 2 );
break;
}
/* Sleep until there is only AOUT_BUFFER_DURATION/2 worth of audio
* left to play in the aout plugin, then we can start refill the
* plugin's buffer */
if( i_units > (i_buffer_limit/2) )
msleep( (i_units - i_buffer_limit/2) * AOUT_BUFFER_DURATION
/ i_buffer_limit );
}
vlc_mutex_lock( &p_aout->fifos_lock );
for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
{
aout_FreeFifo( &p_aout->fifo[i_fifo] );
}
vlc_mutex_unlock( &p_aout->fifos_lock );
}
/* Following functions are local */
/*****************************************************************************
* InitializeIncrement: change i_x/i_y to i_a+i_b/i_c
*****************************************************************************/
static inline void InitializeIncrement( aout_increment_t *p_inc,
int i_x, int i_y )
{
p_inc->i_r = -i_y;
p_inc->i_a = 0;
while ( i_x >= i_y )
{
p_inc->i_a++;
i_x -= i_y;
}
p_inc->i_b = i_x;
p_inc->i_c = i_y;
}
/*****************************************************************************
* UpdateIncrement
*****************************************************************************/
static inline void UpdateIncrement( aout_increment_t *p_inc, int *pi_integer )
{
if( (p_inc->i_r += p_inc->i_b) >= 0 )
{
*pi_integer += p_inc->i_a + 1;
p_inc->i_r -= p_inc->i_c;
}
else
{
*pi_integer += p_inc->i_a;
}
}
/*****************************************************************************
* FillBuffer: Read data from decoder fifo, and put it in S32_buffer
*****************************************************************************/
static void FillBuffer( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
{
int i_buffer = 0;
int i_buffer_limit, i_units;
switch ( p_fifo->i_format )
{
case AOUT_FIFO_PCM:
i_units = p_aout->i_units;
/* While there are empty frames in the buffer, fill them */
while ( i_units > 0 )
{
/* If there is no next frame, wait for one */
if( !p_fifo->b_next_frame )
{
if( NextFrame(p_aout, p_fifo, p_aout->date +
((((mtime_t)(i_buffer >> 1)) * 1000000) /
((mtime_t)p_aout->i_rate))) )
{
break;
}
}
i_buffer_limit = p_aout->i_units * p_aout->i_channels;
while ( i_buffer < i_buffer_limit )
{
/* FIXME: make this more generic */
if( p_aout->i_channels == 2 )
{
p_aout->s32_buffer[i_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->i_unit] );
p_aout->s32_buffer[i_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->i_unit+1] );
}
else if( p_aout->i_channels == 1 )
{
p_aout->s32_buffer[i_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->i_unit] );
}
else
{
msg_Err( p_aout, "unsupported number of channels" );
}
UpdateIncrement(&p_fifo->unit_increment, &p_fifo->i_unit);
if( p_fifo->i_unit >= p_fifo->i_unit_limit )
{
p_fifo->i_unit -= p_fifo->i_unit_limit;
}
}
if( p_fifo->i_units > i_units )
{
p_fifo->i_units -= i_units;
break;
}
else
{
i_units -= p_fifo->i_units;
vlc_mutex_lock( &p_fifo->data_lock );
p_fifo->i_start_frame = p_fifo->i_next_frame;
/* p_fifo->b_start_frame = 1; */
p_fifo->i_next_frame = AOUT_FIFO_INC( p_fifo->i_next_frame );
p_fifo->b_next_frame = 0;
vlc_cond_signal( &p_fifo->data_wait );
vlc_mutex_unlock( &p_fifo->data_lock );
}
}
break;
default:
break;
}
}
static int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo,
mtime_t aout_date )
{
int i_units, i_units_dist, i_rate;
mtime_t i_delta;
/* We take the lock */
vlc_mutex_lock( &p_fifo->data_lock );
if ( p_fifo->b_die )
{
vlc_mutex_unlock( &p_fifo->data_lock );
return( -1 );
}
/* Are we looking for a dated start frame ? */
if ( !p_fifo->b_start_frame )
{
while ( p_fifo->i_start_frame != p_fifo->i_end_frame )
{
if ( p_fifo->date[p_fifo->i_start_frame] != LAST_MDATE )
{
p_fifo->b_start_frame = 1;
p_fifo->i_next_frame = AOUT_FIFO_INC( p_fifo->i_start_frame );
p_fifo->i_unit = p_fifo->i_start_frame *
(p_fifo->i_frame_size / p_fifo->i_channels);
break;
}
p_fifo->i_start_frame = AOUT_FIFO_INC( p_fifo->i_start_frame );
}
if ( p_fifo->i_start_frame == p_fifo->i_end_frame )
{
vlc_mutex_unlock( &p_fifo->data_lock );
return( -1 );
}
}
/* We are looking for the next dated frame */
/* FIXME : is the output fifo full ?? -- pretty unlikely given its size */
while ( !p_fifo->b_next_frame )
{
while ( p_fifo->i_next_frame != p_fifo->i_end_frame )
{
if ( p_fifo->date[p_fifo->i_next_frame] != LAST_MDATE )
{
p_fifo->b_next_frame = 1;
break;
}
p_fifo->i_next_frame = AOUT_FIFO_INC( p_fifo->i_next_frame );
}
while ( p_fifo->i_next_frame == p_fifo->i_end_frame )
{
vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
if ( p_fifo->b_die )
{
vlc_mutex_unlock( &p_fifo->data_lock );
return( -1 );
}
}
}
i_units = ((p_fifo->i_next_frame - p_fifo->i_start_frame) & AOUT_FIFO_SIZE)
* (p_fifo->i_frame_size / p_fifo->i_channels);
i_delta = aout_date - p_fifo->date[p_fifo->i_start_frame];
/* Resample if delta is too long */
if( abs(i_delta) > MAX_DELTA )
{
i_rate = p_fifo->i_rate + (i_delta / 256);
}
else
{
i_rate = p_fifo->i_rate;
}
InitializeIncrement( &p_fifo->unit_increment, i_rate, p_aout->i_rate );
/* Calculate how many units we're going to write */
i_units_dist = p_fifo->i_unit - p_fifo->i_start_frame
* (p_fifo->i_frame_size / p_fifo->i_channels);
/* Manage the fifo wrapping */
if( i_units_dist > p_fifo->i_unit_limit / 2 )
{
i_units -= (i_units_dist - p_fifo->i_unit_limit);
}
else if( i_units_dist < - p_fifo->i_unit_limit / 2 )
{
i_units -= (i_units_dist + p_fifo->i_unit_limit);
}
else
{
i_units -= i_units_dist;
}
p_fifo->i_units = 1 + ( i_units * p_aout->i_rate / i_rate );
/* We release the lock before leaving */
vlc_mutex_unlock( &p_fifo->data_lock );
return( 0 );
}
/*****************************************************************************
* aout_pcm.h: PCM audio output functions
*****************************************************************************
* Copyright (C) 1999-2002 VideoLAN
* $Id: aout_pcm.h,v 1.1 2002/02/24 22:06:50 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
*
* 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.
*****************************************************************************/
void aout_PCMThread( aout_thread_t * p_aout );
/*****************************************************************************
* aout_spdif.c: A52 passthrough output
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: aout_spdif.c,v 1.30 2002/08/04 17:23:44 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Stphane Borel <stef@via.ecp.fr>
*
* 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 <stdlib.h> /* calloc(), malloc(), free() */
#include <string.h> /* memset() */
#include <vlc/vlc.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "audio_output.h"
#include "aout_spdif.h"
/****************************************************************************
* iec958_build_burst: builds an iec958/spdif frame
****************************************************************************/
void iec958_build_burst( u8 * p_buf, aout_fifo_t * p_fifo )
{
const u8 p_sync[6] = { 0x72, 0xF8, 0x1F, 0x4E, 0x01, 0x00 };
int i_length = p_fifo->i_frame_size;
#ifndef HAVE_SWAB
/* Skip the first byte if i_length is odd */
u16 * p_in = (u16 *)( p_fifo->buffer + ( i_length & 0x1 ) );
u16 * p_out = (u16 *)p_buf;
#endif
/* Add the spdif headers */
memcpy( p_buf, p_sync, 6 );
p_buf[6] = ( i_length * 8 ) & 0xFF;
p_buf[7] = ( ( i_length * 8 ) >> 8 ) & 0xFF;
#ifdef HAVE_SWAB
swab( p_fifo->buffer + p_fifo->i_start_frame * i_length,
p_buf + 8, i_length );
#else
/* i_length should be even */
i_length &= ~0x1;
while( i_length )
{
*p_out = ( (*p_in & 0x00ff) << 16 ) | ( (*p_in & 0xff00) >> 16 );
p_in++;
p_out++;
i_length -= 2;
}
#endif
/* Add zeroes to complete the spdif frame,
* they will be ignored by the decoder */
memset( p_buf + 8 + i_length, 0, SPDIF_FRAME_SIZE - 8 - i_length );
}
/*****************************************************************************
* aout_SpdifThread: audio output thread that sends raw spdif data
* to an external decoder
*****************************************************************************
* This output thread is quite specific as it can only handle one fifo now.
*
* Note: spdif can demux up to 8 A52 streams, and can even take
* care of time stamps (cf A52 spec) but I'm not sure all decoders
* implement it.
*****************************************************************************/
void aout_SpdifThread( aout_thread_t * p_aout )
{
int i_fifo;
mtime_t m_frame_time = 0;
mtime_t m_play;
mtime_t m_old;
while( !p_aout->b_die )
{
i_fifo = 0;
/* Find spdif fifo */
while( ( p_aout->fifo[i_fifo].i_format != AOUT_FIFO_SPDIF ) &&
( i_fifo < AOUT_MAX_FIFOS ) && !p_aout->b_die )
{
i_fifo++;
}
m_old = 0;
while( !p_aout->b_die &&
!p_aout->fifo[i_fifo].b_die )
{
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
if( !AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) )
{
/* Copy data from fifo to buffer to release the
* lock earlier */
iec958_build_burst( p_aout->buffer,
&p_aout->fifo[i_fifo] );
m_play = p_aout->fifo[i_fifo].date[p_aout->fifo[i_fifo].
i_start_frame];
p_aout->fifo[i_fifo].i_start_frame =
(p_aout->fifo[i_fifo].i_start_frame + 1 )
& AOUT_FIFO_SIZE;
/* Compute the theorical duration of an A52 frame */
m_frame_time = 1000000 * A52_FRAME_SIZE
/ p_aout->fifo[i_fifo].i_rate;
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/* Play spdif frame to the external decoder
* the kernel driver will sleep until the
* dsp buffer is empty enough to accept the data */
if( m_play > ( mdate() - m_frame_time ) )
{
/* check continuity */
if( (m_play - m_old) != m_frame_time )
{
mwait( m_play - m_frame_time );
}
else
{
mwait( m_play - 2 * m_frame_time );
}
m_old = m_play;
p_aout->pf_getbufinfo( p_aout, 0 );
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer,
SPDIF_FRAME_SIZE );
}
}
else
{
msg_Warn( p_aout, "empty spdif fifo" );
while( AOUT_FIFO_ISEMPTY( p_aout->fifo[i_fifo] ) &&
!p_aout->b_die &&
!p_aout->fifo[i_fifo].b_die )
{
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
msleep( m_frame_time );
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
}
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
}
}
vlc_mutex_lock( &p_aout->fifos_lock );
aout_FreeFifo( &p_aout->fifo[i_fifo] );
vlc_mutex_unlock( &p_aout->fifos_lock );
}
return;
}
/*****************************************************************************
* aout_spdif.h: A52 passthrough output
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: aout_spdif.h,v 1.2 2002/08/04 17:23:44 sam Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Stéphane Borel <stef@via.ecp.fr>
*
* 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.
*****************************************************************************/
void aout_SpdifThread ( aout_thread_t * p_aout );
/*****************************************************************************
* audio_output.c : audio output thread
* audio_output.c : audio output instance
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: audio_output.c,v 1.89 2002/08/04 20:04:11 sam Exp $
* Copyright (C) 2002 VideoLAN
* $Id: audio_output.c,v 1.90 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Michel Kaempf <maxx@via.ecp.fr>
* Cyril Deguet <asmax@via.ecp.fr>
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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
......@@ -30,229 +29,170 @@
#include <vlc/vlc.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h> /* getpid() */
#endif
#ifdef WIN32 /* getpid() for win32 is located in process.h */
# include <process.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#include "audio_output.h"
#include "aout_pcm.h"
#include "aout_spdif.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int aout_SpawnThread ( aout_thread_t * p_aout );
#include "aout_internal.h"
/*****************************************************************************
* aout_CreateThread: initialize audio thread
* aout_NewInstance: initialize aout structure
*****************************************************************************/
aout_thread_t *aout_CreateThread( vlc_object_t *p_parent,
int i_channels, int i_rate )
aout_instance_t * __aout_NewInstance( vlc_object_t * p_parent )
{
aout_thread_t * p_aout; /* thread descriptor */
int i_format;
aout_instance_t * p_aout;
/* Allocate descriptor */
/* Allocate descriptor. */
p_aout = vlc_object_create( p_parent, VLC_OBJECT_AOUT );
if( p_aout == NULL )
{
return NULL;
}
p_aout->i_latency = 0;
p_aout->i_rate = config_GetInt( p_aout, "rate" );
p_aout->i_channels = config_GetInt( p_aout, "mono" ) ? 1 : 2;
i_format = config_GetInt( p_aout, "audio-format" );
if( ( !i_format ) || ( i_format > 8 ) )
{
p_aout->i_format = AOUT_FMT_S16_NE;
}
else
{
p_aout->i_format = 1 << ( i_format + 2 );
}
/* Initialize members. */
vlc_mutex_init( p_parent, &p_aout->input_lock );
vlc_cond_init( p_parent, &p_aout->input_signal );
p_aout->i_inputs_active = 0;
p_aout->b_change_requested = 0;
p_aout->i_nb_inputs = 0;
if( p_aout->i_rate == 0 )
{
msg_Err( p_aout, "null sample rate" );
vlc_object_destroy( p_aout );
return NULL;
}
vlc_mutex_init( p_parent, &p_aout->mixer_lock );
vlc_cond_init( p_parent, &p_aout->mixer_signal );
p_aout->b_mixer_active = 0;
/* Choose the best module */
p_aout->p_module = module_Need( p_aout, "audio output", "$aout" );
if( p_aout->p_module == NULL )
{
msg_Err( p_aout, "no suitable aout module" );
vlc_object_destroy( p_aout );
return NULL;
}
vlc_object_attach( p_aout, p_parent->p_vlc );
/*
* Initialize audio device
*/
if ( p_aout->pf_setformat( p_aout ) )
{
module_Unneed( p_aout, p_aout->p_module );
vlc_object_destroy( p_aout );
return NULL;
}
return p_aout;
}
/* Initialize the volume level */
p_aout->i_volume = config_GetInt( p_aout, "volume" );
p_aout->i_savedvolume = 0;
/*****************************************************************************
* aout_DeleteInstance: destroy aout structure
*****************************************************************************/
void aout_DeleteInstance( aout_instance_t * p_aout )
{
vlc_mutex_destroy( &p_aout->input_lock );
vlc_cond_destroy( &p_aout->input_signal );
vlc_mutex_destroy( &p_aout->mixer_lock );
vlc_cond_destroy( &p_aout->mixer_signal );
/* FIXME: maybe it would be cleaner to change SpawnThread prototype
* see vout to handle status correctly ?? however, it is not critical since
* this thread is only called in main and all calls are blocking */
if( aout_SpawnThread( p_aout ) )
{
module_Unneed( p_aout, p_aout->p_module );
/* Free structure. */
vlc_object_detach_all( p_aout );
vlc_object_destroy( p_aout );
return NULL;
}
vlc_object_attach( p_aout, p_parent->p_vlc );
return p_aout;
}
/*****************************************************************************
* aout_SpawnThread
* aout_BufferNew : ask for a new empty buffer
*****************************************************************************/
static int aout_SpawnThread( aout_thread_t * p_aout )
aout_buffer_t * aout_BufferNew( aout_instance_t * p_aout,
aout_input_t * p_input,
size_t i_nb_samples )
{
int i_index, i_bytes;
void (* pf_aout_thread)( aout_thread_t * ) = NULL;
char *psz_format;
aout_buffer_t * p_buffer;
/* Initialize the fifos lock */
vlc_mutex_init( p_aout, &p_aout->fifos_lock );
/* This necessarily allocates in the heap. */
aout_BufferAlloc( &p_input->input_alloc, (u64)(1000000 * i_nb_samples)
/ p_input->input.i_rate,
NULL, p_buffer );
p_buffer->i_nb_samples = i_nb_samples;
/* Initialize audio fifos : set all fifos as empty and initialize locks */
for ( i_index = 0; i_index < AOUT_MAX_FIFOS; i_index++ )
if ( p_buffer == NULL )
{
p_aout->fifo[i_index].i_format = AOUT_FIFO_NONE;
vlc_mutex_init( p_aout, &p_aout->fifo[i_index].data_lock );
vlc_cond_init( p_aout, &p_aout->fifo[i_index].data_wait );
msg_Err( p_aout, "NULL buffer !" );
}
/* Compute the size (in audio units) of the audio output buffer. Although
* AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
* in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
p_aout->i_units = (s64)p_aout->i_rate * AOUT_BUFFER_DURATION / 1000000;
/* Make pf_aout_thread point to the right thread function, and compute the
* byte size of the audio output buffer */
switch ( p_aout->i_format )
else
{
case AOUT_FMT_U8:
pf_aout_thread = aout_PCMThread;
psz_format = "unsigned 8 bits";
i_bytes = p_aout->i_units * p_aout->i_channels;
break;
case AOUT_FMT_S8:
pf_aout_thread = aout_PCMThread;
psz_format = "signed 8 bits";
i_bytes = p_aout->i_units * p_aout->i_channels;
break;
case AOUT_FMT_U16_LE:
case AOUT_FMT_U16_BE:
pf_aout_thread = aout_PCMThread;
psz_format = "unsigned 16 bits";
i_bytes = 2 * p_aout->i_units * p_aout->i_channels;
break;
p_buffer->start_date = p_buffer->end_date = 0;
}
case AOUT_FMT_S16_LE:
case AOUT_FMT_S16_BE:
pf_aout_thread = aout_PCMThread;
psz_format = "signed 16 bits";
i_bytes = 2 * p_aout->i_units * p_aout->i_channels;
break;
return p_buffer;
}
case AOUT_FMT_A52:
pf_aout_thread = aout_SpdifThread;
psz_format = "A52 pass-through";
i_bytes = SPDIF_FRAME_SIZE;
break;
/*****************************************************************************
* aout_BufferDelete : destroy an undecoded buffer
*****************************************************************************/
void aout_BufferDelete( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer )
{
aout_BufferFree( p_buffer );
}
default:
msg_Err( p_aout, "unknown audio output format %i",
p_aout->i_format );
return( -1 );
}
/*****************************************************************************
* aout_BufferPlay : filter & mix the decoded buffer
*****************************************************************************/
void aout_BufferPlay( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer )
{
vlc_bool_t b_run_mixer = 0;
/* Allocate the memory needed by the audio output buffers, and set to zero
* the s32 buffer's memory */
p_aout->buffer = malloc( i_bytes );
if ( p_aout->buffer == NULL )
if ( p_buffer->start_date == 0 )
{
msg_Err( p_aout, "out of memory" );
return( -1 );
msg_Warn( p_aout, "non-dated buffer received" );
aout_BufferFree( p_buffer );
}
p_aout->s32_buffer = (s32 *)calloc( p_aout->i_units,
sizeof(s32) * p_aout->i_channels );
if ( p_aout->s32_buffer == NULL )
else
{
msg_Err( p_aout, "out of memory" );
free( p_aout->buffer );
return( -1 );
p_buffer->end_date = p_buffer->start_date
+ (mtime_t)(p_buffer->i_nb_samples * 1000000)
/ p_input->input.i_rate;
}
/* Rough estimate of the playing date */
p_aout->date = mdate() + p_aout->p_vlc->i_desync;
aout_InputPlay( p_aout, p_input, p_buffer );
/* Launch the thread */
if ( vlc_thread_create( p_aout, "audio output", pf_aout_thread, 0 ) )
/* Run the mixer if it is able to run. */
vlc_mutex_lock( &p_aout->mixer_lock );
if ( !p_aout->b_mixer_active )
{
msg_Err( p_aout, "cannot spawn audio output thread" );
free( p_aout->buffer );
free( p_aout->s32_buffer );
return( -1 );
p_aout->b_mixer_active = 1;
b_run_mixer = 1;
}
vlc_mutex_unlock( &p_aout->mixer_lock );
msg_Dbg( p_aout, "%s thread spawned, %i channels, rate %i",
psz_format, p_aout->i_channels, p_aout->i_rate );
return( 0 );
if ( b_run_mixer )
{
aout_MixerRun( p_aout );
vlc_mutex_lock( &p_aout->mixer_lock );
p_aout->b_mixer_active = 0;
vlc_cond_broadcast( &p_aout->mixer_signal );
vlc_mutex_unlock( &p_aout->mixer_lock );
}
}
/*****************************************************************************
* aout_DestroyThread
* aout_FormatToBytes : return the number bytes/sample for format
* (didn't know where else to put it)
*****************************************************************************/
void aout_DestroyThread( aout_thread_t * p_aout )
int aout_FormatToBytes( audio_sample_format_t * p_format )
{
int i_index;
int i_result;
/* Ask thread to kill itself and wait until it's done */
p_aout->b_die = 1;
switch ( p_format->i_format )
{
case AOUT_FMT_U8:
case AOUT_FMT_S8:
i_result = 1;
break;
vlc_thread_join( p_aout );
case AOUT_FMT_U16_LE:
case AOUT_FMT_U16_BE:
case AOUT_FMT_S16_LE:
case AOUT_FMT_S16_BE:
i_result = 2;
break;
/* Free the allocated memory */
free( p_aout->buffer );
free( p_aout->s32_buffer );
case AOUT_FMT_FLOAT32:
case AOUT_FMT_FIXED32:
i_result = 4;
break;
/* Destroy the condition and mutex locks */
for ( i_index = 0; i_index < AOUT_MAX_FIFOS; i_index++ )
{
vlc_mutex_destroy( &p_aout->fifo[i_index].data_lock );
vlc_cond_destroy( &p_aout->fifo[i_index].data_wait );
}
vlc_mutex_destroy( &p_aout->fifos_lock );
case AOUT_FMT_A52:
i_result = 1; /* This is a bit special... sample == byte */
break;
/* Release the aout module */
module_Unneed( p_aout, p_aout->p_module );
default:
i_result = 0; /* will segfault much sooner... */
}
/* Free structure */
vlc_object_destroy( p_aout );
return i_result * p_format->i_channels;
}
/*****************************************************************************
* filters.c : audio output filters management
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: filters.c,v 1.1 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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 <stdlib.h> /* calloc(), malloc(), free() */
#include <string.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#include <vlc/vlc.h>
#include "audio_output.h"
#include "aout_internal.h"
/*****************************************************************************
* aout_FiltersCreatePipeline: create a filters pipeline to transform a sample
* format to another
*****************************************************************************
* TODO : allow the user to add/remove specific filters
*****************************************************************************/
int aout_FiltersCreatePipeline( aout_instance_t * p_aout,
aout_filter_t ** pp_filters,
int * pi_nb_filters,
audio_sample_format_t * p_input_format,
audio_sample_format_t * p_output_format )
{
if ( AOUT_FMTS_IDENTICAL( p_input_format, p_output_format ) )
{
msg_Dbg( p_aout, "no need for any filter" );
*pi_nb_filters = 0;
return 0;
}
pp_filters[0] = vlc_object_create( p_aout, sizeof(aout_filter_t) );
if ( pp_filters[0] == NULL )
{
return -1;
}
vlc_object_attach( pp_filters[0], p_aout );
/* Try to find a filter to do the whole conversion. */
memcpy( &pp_filters[0]->input, p_input_format,
sizeof(audio_sample_format_t) );
memcpy( &pp_filters[0]->output, p_output_format,
sizeof(audio_sample_format_t) );
pp_filters[0]->p_module = module_Need( pp_filters[0], "audio filter",
NULL );
if ( pp_filters[0]->p_module != NULL )
{
msg_Dbg( p_aout, "found a filter for the whole conversion" );
*pi_nb_filters = 1;
return 0;
}
/* Split the conversion : format | rate, or rate | format. */
pp_filters[0]->output.i_format = pp_filters[0]->input.i_format;
pp_filters[0]->p_module = module_Need( pp_filters[0], "audio filter",
NULL );
if ( pp_filters[0]->p_module == NULL )
{
/* Then, start with the format conversion. */
memcpy( &pp_filters[0]->output, p_output_format,
sizeof(audio_sample_format_t) );
pp_filters[0]->output.i_rate = pp_filters[0]->input.i_rate;
pp_filters[0]->p_module = module_Need( pp_filters[0], "audio filter",
NULL );
if ( pp_filters[0]->p_module == NULL )
{
msg_Err( p_aout, "couldn't find a filter for any conversion" );
vlc_object_detach_all( pp_filters[0] );
vlc_object_destroy( pp_filters[0] );
return -1;
}
}
/* Find a filter for the rest. */
pp_filters[1] = vlc_object_create( p_aout, sizeof(aout_filter_t) );
if ( pp_filters[1] == NULL )
{
vlc_object_detach_all( pp_filters[0] );
vlc_object_destroy( pp_filters[0] );
return -1;
}
vlc_object_attach( pp_filters[1], p_aout );
memcpy( &pp_filters[1]->input, &pp_filters[0]->output,
sizeof(audio_sample_format_t) );
memcpy( &pp_filters[1]->output, p_output_format,
sizeof(audio_sample_format_t) );
pp_filters[1]->p_module = module_Need( pp_filters[1], "audio filter",
NULL );
if ( pp_filters[1]->p_module == NULL )
{
msg_Err( p_aout,
"couldn't find a filter for the 2nd part of the conversion" );
vlc_object_detach_all( pp_filters[0] );
vlc_object_destroy( pp_filters[0] );
vlc_object_detach_all( pp_filters[1] );
vlc_object_destroy( pp_filters[1] );
return -1;
}
msg_Dbg( p_aout, "filter pipeline made of two filters" );
*pi_nb_filters = 2;
return 0;
}
/*****************************************************************************
* aout_FiltersDestroyPipeline: deallocate a filters pipeline
*****************************************************************************/
void aout_FiltersDestroyPipeline( aout_instance_t * p_aout,
aout_filter_t ** pp_filters,
int i_nb_filters )
{
int i;
for ( i = 0; i < i_nb_filters; i++ )
{
module_Unneed( pp_filters[i], pp_filters[i]->p_module );
vlc_object_detach_all( pp_filters[i] );
vlc_object_destroy( pp_filters[i] );
}
}
/*****************************************************************************
* aout_FiltersHintBuffers: fill in aout_alloc_t structures to optimize
* buffer allocations
*****************************************************************************/
void aout_FiltersHintBuffers( aout_instance_t * p_aout,
aout_filter_t ** pp_filters,
int i_nb_filters, aout_alloc_t * p_first_alloc )
{
int i;
for ( i = i_nb_filters - 1; i >= 0; i-- )
{
aout_filter_t * p_filter = pp_filters[i];
int i_output_size = aout_FormatToBytes( &p_filter->output )
* p_filter->output.i_rate;
int i_input_size = aout_FormatToBytes( &p_filter->input )
* p_filter->input.i_rate;
p_first_alloc->i_bytes_per_sec = __MAX( p_first_alloc->i_bytes_per_sec,
i_output_size );
if ( p_filter->b_in_place )
{
p_first_alloc->i_bytes_per_sec = __MAX(
p_first_alloc->i_bytes_per_sec,
i_input_size );
}
else
{
/* We're gonna need a buffer allocation. */
memcpy( &p_filter->output_alloc, p_first_alloc,
sizeof(aout_alloc_t) );
p_first_alloc->i_alloc_type = AOUT_ALLOC_STACK;
p_first_alloc->i_bytes_per_sec = i_input_size;
}
}
}
/*****************************************************************************
* aout_FiltersPlay: play a buffer
*****************************************************************************/
void aout_FiltersPlay( aout_instance_t * p_aout,
aout_filter_t ** pp_filters,
int i_nb_filters, aout_buffer_t ** pp_input_buffer )
{
int i;
for ( i = 0; i < i_nb_filters; i++ )
{
aout_filter_t * p_filter = pp_filters[i];
aout_buffer_t * p_output_buffer;
aout_BufferAlloc( &p_filter->output_alloc,
(u64)((*pp_input_buffer)->i_nb_samples * 1000000)
/ p_filter->output.i_rate, *pp_input_buffer,
p_output_buffer );
if ( p_output_buffer == NULL )
{
msg_Err( p_aout, "out of memory" );
return;
}
/* Please note that p_output_buffer->i_nb_samples shall be set by
* the filter plug-in. */
p_filter->pf_do_work( p_aout, p_filter, *pp_input_buffer,
p_output_buffer );
if ( !p_filter->b_in_place )
{
aout_BufferFree( *pp_input_buffer );
*pp_input_buffer = p_output_buffer;
}
}
}
/*****************************************************************************
* input.c : internal management of input streams for the audio output
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: input.c,v 1.1 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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 <stdlib.h> /* calloc(), malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#include "audio_output.h"
#include "aout_internal.h"
/*****************************************************************************
* aout_InputNew : allocate a new input and rework the filter pipeline
*****************************************************************************/
static aout_input_t * InputNew( aout_instance_t * p_aout,
audio_sample_format_t * p_format )
{
aout_input_t * p_input = malloc(sizeof(aout_input_t));
if ( p_input == NULL ) return NULL;
vlc_mutex_lock( &p_aout->mixer_lock );
while ( p_aout->b_mixer_active )
{
vlc_cond_wait( &p_aout->mixer_signal, &p_aout->mixer_lock );
}
if ( p_aout->i_nb_inputs == 0 )
{
/* Recreate the output using the new format. */
if ( aout_OutputNew( p_aout, p_format ) < 0 )
{
free( p_input );
return NULL;
}
}
else
{
aout_MixerDelete( p_aout );
}
memcpy( &p_input->input, p_format,
sizeof(audio_sample_format_t) );
/* Prepare FIFO. */
aout_FifoInit( p_aout, &p_input->fifo );
p_input->p_first_byte_to_mix = NULL;
/* Create filters. */
if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
&p_input->i_nb_filters, &p_input->input,
&p_aout->mixer.input ) < 0 )
{
msg_Err( p_aout, "couldn't set an input pipeline" );
aout_FifoDestroy( p_aout, &p_input->fifo );
free( p_input );
if ( !p_aout->i_nb_inputs )
{
aout_OutputDelete( p_aout );
}
return NULL;
}
p_aout->pp_inputs[p_aout->i_nb_inputs] = p_input;
p_aout->i_nb_inputs++;
if ( aout_MixerNew( p_aout ) < 0 )
{
p_aout->i_nb_inputs--;
aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters,
p_input->i_nb_filters );
aout_FifoDestroy( p_aout, &p_input->fifo );
free( p_input );
if ( !p_aout->i_nb_inputs )
{
aout_OutputDelete( p_aout );
}
}
/* Prepare hints for the buffer allocator. */
p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
p_input->input_alloc.i_bytes_per_sec = -1;
aout_FiltersHintBuffers( p_aout, p_input->pp_filters,
p_input->i_nb_filters,
&p_input->input_alloc );
/* i_bytes_per_sec is still == -1 if no filters */
p_input->input_alloc.i_bytes_per_sec = __MAX(
p_input->input_alloc.i_bytes_per_sec,
aout_FormatToBytes( &p_input->input )
* p_input->input.i_rate );
/* Allocate in the heap, it is more convenient for the decoder. */
p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
vlc_mutex_unlock( &p_aout->mixer_lock );
msg_Dbg( p_aout, "input 0x%x created", p_input );
return p_input;
}
aout_input_t * __aout_InputNew( vlc_object_t * p_this,
aout_instance_t ** pp_aout,
audio_sample_format_t * p_format )
{
/* Create an audio output if there is none. */
*pp_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT, FIND_ANYWHERE );
if( *pp_aout == NULL )
{
msg_Dbg( p_this, "no aout present, spawning one" );
*pp_aout = aout_NewInstance( p_this );
/* Everything failed, I'm a loser, I just wanna die */
if( *pp_aout == NULL )
{
return NULL;
}
}
else
{
vlc_object_release( *pp_aout );
}
return InputNew( *pp_aout, p_format );
}
/*****************************************************************************
* aout_InputDelete : delete an input
*****************************************************************************/
void aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input )
{
int i_input;
msg_Dbg( p_aout, "input 0x%x destroyed", p_input );
vlc_mutex_lock( &p_aout->mixer_lock );
while ( p_aout->b_mixer_active )
{
vlc_cond_wait( &p_aout->mixer_signal, &p_aout->mixer_lock );
}
for ( i_input = 0; i_input < p_aout->i_nb_inputs; i_input++ )
{
if ( p_aout->pp_inputs[i_input] == p_input )
{
break;
}
}
if ( i_input == p_aout->i_nb_inputs )
{
msg_Err( p_aout, "cannot find an input to delete" );
return;
}
/* Remove the input from the list. */
memmove( &p_aout->pp_inputs[i_input], &p_aout->pp_inputs[i_input + 1],
(AOUT_MAX_INPUTS - i_input - 1) * sizeof(aout_input_t *) );
p_aout->i_nb_inputs--;
vlc_mutex_unlock( &p_aout->mixer_lock );
aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters,
p_input->i_nb_filters );
aout_FifoDestroy( p_aout, &p_input->fifo );
free( p_input );
if ( !p_aout->i_nb_inputs )
{
aout_OutputDelete( p_aout );
aout_MixerDelete( p_aout );
}
}
/*****************************************************************************
* aout_InputPlay : play a buffer
*****************************************************************************/
void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
aout_buffer_t * p_buffer )
{
vlc_mutex_lock( &p_aout->input_lock );
while( p_aout->b_change_requested )
{
vlc_cond_wait( &p_aout->input_signal, &p_aout->input_lock );
}
p_aout->i_inputs_active++;
vlc_mutex_unlock( &p_aout->input_lock );
aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters,
&p_buffer );
aout_FifoPush( p_aout, &p_input->fifo, p_buffer );
vlc_mutex_lock( &p_aout->input_lock );
p_aout->i_inputs_active--;
vlc_cond_broadcast( &p_aout->input_signal );
vlc_mutex_unlock( &p_aout->input_lock );
}
/*****************************************************************************
* mixer.c : audio output mixing operations
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: mixer.c,v 1.1 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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 <stdlib.h> /* calloc(), malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#ifdef HAVE_ALLOCA_H
# include <alloca.h>
#endif
#include "audio_output.h"
#include "aout_internal.h"
/*****************************************************************************
* aout_MixerNew: prepare a mixer plug-in
*****************************************************************************/
int aout_MixerNew( aout_instance_t * p_aout )
{
p_aout->mixer.p_module = module_Need( p_aout, "audio mixer", NULL );
if ( p_aout->mixer.p_module == NULL )
{
msg_Err( p_aout, "no suitable aout mixer" );
return -1;
}
return 0;
}
/*****************************************************************************
* aout_MixerDelete: delete the mixer
*****************************************************************************/
void aout_MixerDelete( aout_instance_t * p_aout )
{
module_Unneed( p_aout, p_aout->mixer.p_module );
}
/*****************************************************************************
* aout_MixerRun: entry point for the mixer & post-filters processing
*****************************************************************************/
void aout_MixerRun( aout_instance_t * p_aout )
{
int i;
aout_buffer_t * p_output_buffer;
/* See if we have enough data to prepare a new buffer for the audio
* output. */
mtime_t wanted_date = 0, first_date = 0;
for ( i = 0; i < p_aout->i_nb_inputs; i++ )
{
aout_fifo_t * p_fifo = &p_aout->pp_inputs[i]->fifo;
aout_buffer_t * p_buffer;
vlc_mutex_lock( &p_fifo->lock );
for ( p_buffer = p_fifo->p_first; p_buffer != NULL;
p_buffer = p_buffer->p_next )
{
if ( !wanted_date )
{
if ( !p_aout->output.last_date )
{
first_date = p_buffer->start_date;
wanted_date = p_buffer->start_date
+ (mtime_t)p_aout->output.i_nb_samples * 1000000
/ p_aout->output.output.i_rate;
}
else
{
first_date = p_aout->output.last_date;
wanted_date = p_aout->output.last_date
+ (mtime_t)p_aout->output.i_nb_samples * 1000000
/ p_aout->output.output.i_rate;
}
}
if ( p_buffer->end_date >= wanted_date ) break;
}
vlc_mutex_unlock( &p_fifo->lock );
if ( p_buffer == NULL ) break;
}
if ( i < p_aout->i_nb_inputs )
{
/* Interrupted before the end... We can't run. */
return;
}
/* Run the mixer. */
aout_BufferAlloc( &p_aout->mixer.output_alloc,
(u64)(p_aout->output.i_nb_samples * 1000000)
/ p_aout->output.output.i_rate, NULL,
p_output_buffer );
if ( p_output_buffer == NULL )
{
msg_Err( p_aout, "out of memory" );
return;
}
p_output_buffer->i_nb_samples = p_aout->output.i_nb_samples;
p_output_buffer->start_date = first_date;
p_output_buffer->end_date = wanted_date;
p_aout->output.last_date = wanted_date;
p_aout->mixer.pf_do_work( p_aout, p_output_buffer );
aout_OutputPlay( p_aout, p_output_buffer );
}
/*****************************************************************************
* output.c : internal management of output streams for the audio output
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: output.c,v 1.1 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
* 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 <stdlib.h> /* calloc(), malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#include "audio_output.h"
#include "aout_internal.h"
/*****************************************************************************
* aout_OutputNew : allocate a new output and rework the filter pipeline
*****************************************************************************/
int aout_OutputNew( aout_instance_t * p_aout,
audio_sample_format_t * p_format )
{
char * psz_name = config_GetPsz( p_aout, "aout" );
int i_rate = config_GetInt( p_aout, "aout-rate" );
int i_channels = config_GetInt( p_aout, "aout-channels" );
/* Prepare FIFO. */
vlc_mutex_init( p_aout, &p_aout->output.fifo.lock );
p_aout->output.fifo.p_first = NULL;
p_aout->output.fifo.pp_last = &p_aout->output.fifo.p_first;
p_aout->output.last_date = 0;
p_aout->output.p_module = module_Need( p_aout, "audio output",
psz_name );
if ( psz_name != NULL ) free( psz_name );
if ( p_aout->output.p_module == NULL )
{
msg_Err( p_aout, "no suitable aout module" );
return -1;
}
/* Retrieve user defaults. */
memcpy( &p_aout->output.output, p_format, sizeof(audio_sample_format_t) );
if ( i_rate != -1 ) p_aout->output.output.i_rate = i_rate;
if ( i_channels != -1 ) p_aout->output.output.i_channels = i_channels;
if ( p_aout->output.output.i_format != AOUT_FMT_A52 )
{
/* Non-S/PDIF mixer only deals with float32 or fixed32. */
p_aout->output.output.i_format
= (p_aout->p_vlc->i_cpu & CPU_CAPABILITY_FPU) ?
AOUT_FMT_FLOAT32 : AOUT_FMT_FIXED32;
}
/* Find the best output format. */
if ( p_aout->output.pf_setformat( p_aout ) != 0 )
{
msg_Err( p_aout, "couldn't set an output format" );
module_Unneed( p_aout, p_aout->output.p_module );
return -1;
}
msg_Dbg( p_aout, "output format=%d rate=%d channels=%d",
p_aout->output.output.i_format, p_aout->output.output.i_rate,
p_aout->output.output.i_channels );
/* Calculate the resulting mixer output format. */
p_aout->mixer.output.i_channels = p_aout->output.output.i_channels;
p_aout->mixer.output.i_rate = p_aout->output.output.i_rate;
if ( p_aout->output.output.i_format != AOUT_FMT_A52 )
{
p_aout->mixer.output.i_format
= (p_aout->p_vlc->i_cpu & CPU_CAPABILITY_FPU) ?
AOUT_FMT_FLOAT32 : AOUT_FMT_FIXED32;
}
/* Calculate the resulting mixer input format. */
p_aout->mixer.input.i_channels = -1; /* unchanged */
p_aout->mixer.input.i_rate = p_aout->mixer.output.i_rate;
p_aout->mixer.input.i_format = p_aout->mixer.output.i_format;
/* Create filters. */
if ( aout_FiltersCreatePipeline( p_aout, p_aout->output.pp_filters,
&p_aout->output.i_nb_filters,
&p_aout->mixer.output,
&p_aout->output.output ) < 0 )
{
msg_Err( p_aout, "couldn't set an output pipeline" );
module_Unneed( p_aout, p_aout->output.p_module );
return -1;
}
/* Prepare hints for the buffer allocator. */
p_aout->mixer.output_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
p_aout->mixer.output_alloc.i_bytes_per_sec
= aout_FormatToBytes( &p_aout->output.output )
* p_aout->output.output.i_rate;
aout_FiltersHintBuffers( p_aout, p_aout->output.pp_filters,
p_aout->output.i_nb_filters,
&p_aout->mixer.output_alloc );
return 0;
}
/*****************************************************************************
* aout_OutputDelete : delete the output
*****************************************************************************/
void aout_OutputDelete( aout_instance_t * p_aout )
{
module_Unneed( p_aout, p_aout->output.p_module );
aout_FiltersDestroyPipeline( p_aout, p_aout->output.pp_filters,
p_aout->output.i_nb_filters );
aout_FifoDestroy( p_aout, &p_aout->output.fifo );
}
/*****************************************************************************
* aout_OutputPlay : play a buffer
*****************************************************************************/
void aout_OutputPlay( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
{
aout_FiltersPlay( p_aout, p_aout->output.pp_filters,
p_aout->output.i_nb_filters,
&p_buffer );
p_aout->output.pf_play( p_aout, p_buffer );
}
/*****************************************************************************
* aout_OutputNextBuffer : give the audio output plug-in the right buffer
*****************************************************************************/
aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
mtime_t start_date )
{
aout_buffer_t * p_buffer;
vlc_mutex_lock( &p_aout->output.fifo.lock );
p_buffer = p_aout->output.fifo.p_first;
while ( p_buffer != NULL && p_buffer->end_date < start_date )
{
msg_Dbg( p_aout, "audio output is too slow (%lld)",
start_date - p_buffer->end_date );
p_buffer = p_buffer->p_next;
}
p_aout->output.fifo.p_first = p_buffer;
if ( p_buffer == NULL )
{
p_aout->output.fifo.pp_last = &p_aout->output.fifo.p_first;
vlc_mutex_unlock( &p_aout->output.fifo.lock );
msg_Dbg( p_aout, "audio output is starving" );
return NULL;
}
if ( p_buffer->start_date > start_date
+ (mtime_t)p_aout->output.i_nb_samples
* 1000000 / p_aout->output.output.i_rate )
{
vlc_mutex_unlock( &p_aout->output.fifo.lock );
msg_Dbg( p_aout, "audio output is starving (%lld)",
p_buffer->start_date - start_date );
return NULL;
}
/* FIXME : there we should handle the case where start_date is not
* completely equal to p_buffer->start_date. */
p_aout->output.fifo.p_first = p_buffer->p_next;
if ( p_buffer->p_next == NULL )
{
p_aout->output.fifo.pp_last = &p_aout->output.fifo.p_first;
}
vlc_mutex_unlock( &p_aout->output.fifo.lock );
return p_buffer;
}
......@@ -2,7 +2,7 @@
* libvlc.c: main libvlc source
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id: libvlc.c,v 1.20 2002/08/04 20:04:11 sam Exp $
* $Id: libvlc.c,v 1.21 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -608,7 +608,7 @@ vlc_error_t vlc_stop_r( vlc_t *p_vlc )
intf_thread_t *p_intf;
playlist_t *p_playlist;
vout_thread_t *p_vout;
aout_thread_t *p_aout;
aout_instance_t *p_aout;
/* Check that the handle is valid */
if( !p_vlc || p_vlc->i_status != VLC_STATUS_RUNNING )
......@@ -658,9 +658,9 @@ vlc_error_t vlc_stop_r( vlc_t *p_vlc )
msg_Dbg( p_vlc, "removing all audio outputs" );
while( (p_aout = vlc_object_find( p_vlc, VLC_OBJECT_AOUT, FIND_CHILD )) )
{
vlc_object_detach_all( p_aout );
vlc_object_release( p_aout );
aout_DestroyThread( p_aout );
vlc_object_detach_all( (vlc_object_t *)p_aout );
vlc_object_release( (vlc_object_t *)p_aout );
aout_DeleteInstance( p_aout );
}
/* Update the handle status */
......
......@@ -2,7 +2,7 @@
* libvlc.h: main libvlc header
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
* $Id: libvlc.h,v 1.10 2002/08/04 17:23:44 sam Exp $
* $Id: libvlc.h,v 1.11 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -92,11 +92,16 @@
"7 -> MPEG2 audio (unsupported)\n" \
"8 -> A52 pass-through")
#define RATE_TEXT N_("audio output frequency (Hz)")
#define RATE_LONGTEXT N_( \
#define AOUT_RATE_TEXT N_("audio output frequency (Hz)")
#define AOUT_RATE_LONGTEXT N_( \
"You can force the audio output frequency here. Common values are " \
"48000, 44100, 32000, 22050, 16000, 11025, 8000.")
#define AOUT_CHANNELS_TEXT N_("number of channels of audio output")
#define AOUT_CHANNELS_LONGTEXT N_( \
"Mono is 1, stereo is 2. Higher value (used for 5.1) may not be " \
"supported by your audio output module.")
#define DESYNC_TEXT N_("compensate desynchronization of audio (in ms)")
#define DESYNC_LONGTEXT N_( \
"This option allows you to delay the audio output. This can be handy if " \
......@@ -346,9 +351,10 @@ vlc_module_begin();
add_module_with_short( "aout", 'A', "audio output", NULL, NULL,
AOUT_TEXT, AOUT_LONGTEXT );
add_bool( "audio", 1, NULL, AUDIO_TEXT, AUDIO_LONGTEXT );
add_bool( "mono", 0, NULL, MONO_TEXT, MONO_LONGTEXT );
add_integer( "volume", VOLUME_DEFAULT, NULL, VOLUME_TEXT, VOLUME_LONGTEXT );
add_integer( "rate", 44100, NULL, RATE_TEXT, RATE_LONGTEXT );
add_integer( "aout-rate", -1, NULL, AOUT_RATE_TEXT, AOUT_RATE_LONGTEXT );
add_integer( "aout-channels", -1, NULL,
AOUT_CHANNELS_TEXT, AOUT_CHANNELS_LONGTEXT );
add_integer( "desync", 0, NULL, DESYNC_TEXT, DESYNC_LONGTEXT );
add_integer( "audio-format", 0, NULL, FORMAT_TEXT, FORMAT_LONGTEXT );
......
......@@ -180,8 +180,14 @@ static inline const char * module_error( char *psz_buffer )
* STORE_SYMBOLS: store known symbols into p_symbols for plugin access.
*****************************************************************************/
#define STORE_SYMBOLS( p_symbols ) \
(p_symbols)->__aout_CreateFifo_inner = __aout_CreateFifo; \
(p_symbols)->aout_DestroyFifo_inner = aout_DestroyFifo; \
(p_symbols)->__aout_NewInstance_inner = __aout_NewInstance; \
(p_symbols)->aout_DeleteInstance_inner = aout_DeleteInstance; \
(p_symbols)->aout_BufferNew_inner = aout_BufferNew; \
(p_symbols)->aout_BufferDelete_inner = aout_BufferDelete; \
(p_symbols)->aout_BufferPlay_inner = aout_BufferPlay; \
(p_symbols)->__aout_InputNew_inner = __aout_InputNew; \
(p_symbols)->aout_InputDelete_inner = aout_InputDelete; \
(p_symbols)->aout_OutputNextBuffer_inner = aout_OutputNextBuffer; \
(p_symbols)->__config_GetInt_inner = __config_GetInt; \
(p_symbols)->__config_PutInt_inner = __config_PutInt; \
(p_symbols)->__config_GetFloat_inner = __config_GetFloat; \
......
......@@ -2,7 +2,7 @@
* objects.c: vlc_object_t handling
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: objects.c,v 1.13 2002/08/04 18:39:41 sam Exp $
* $Id: objects.c,v 1.14 2002/08/07 21:36:56 massiot Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -38,6 +38,7 @@
#include "video_output.h"
#include "audio_output.h"
#include "aout_internal.h"
#include "vlc_playlist.h"
#include "interface.h"
......@@ -93,7 +94,7 @@ void * __vlc_object_create( vlc_object_t *p_this, int i_type )
psz_type = "video output";
break;
case VLC_OBJECT_AOUT:
i_size = sizeof(aout_thread_t);
i_size = sizeof(aout_instance_t);
psz_type = "audio output";
break;
default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment