Commit b004a661 authored by Sam Hocevar's avatar Sam Hocevar

  * Split audio output into several separate files to make it easier
  to debug. Removed a few redundancies as well.
parent 64bda1b1
...@@ -212,7 +212,12 @@ INPUT = src/input/input_ext-dec.o \ ...@@ -212,7 +212,12 @@ INPUT = src/input/input_ext-dec.o \
src/input/input.o \ src/input/input.o \
src/input/mpeg_system.o src/input/mpeg_system.o
AUDIO_OUTPUT = src/audio_output/audio_output.o AUDIO_OUTPUT = src/audio_output/audio_output.o \
src/audio_output/aout_fifo.o \
src/audio_output/aout_u8.o \
src/audio_output/aout_s8.o \
src/audio_output/aout_u16.o \
src/audio_output/aout_s16.o
VIDEO_OUTPUT = src/video_output/video_output.o \ VIDEO_OUTPUT = src/video_output/video_output.o \
src/video_output/video_text.o \ src/video_output/video_text.o \
......
...@@ -78,6 +78,7 @@ typedef struct aout_fifo_s ...@@ -78,6 +78,7 @@ typedef struct aout_fifo_s
/* See the fifo types below */ /* See the fifo types below */
int i_type; int i_type;
boolean_t b_die; boolean_t b_die;
int i_fifo; /* Just to keep track of the fifo index */
int i_channels; int i_channels;
boolean_t b_stereo; boolean_t b_stereo;
...@@ -202,8 +203,11 @@ typedef struct aout_thread_s ...@@ -202,8 +203,11 @@ typedef struct aout_thread_s
* Prototypes * Prototypes
*****************************************************************************/ *****************************************************************************/
aout_thread_t * aout_CreateThread ( int *pi_status ); aout_thread_t * aout_CreateThread ( int *pi_status );
void aout_DestroyThread ( aout_thread_t *p_aout, int *pi_status ); void aout_DestroyThread ( aout_thread_t *p_aout,
int *pi_status );
aout_fifo_t * aout_CreateFifo ( aout_thread_t *p_aout,
aout_fifo_t * aout_CreateFifo ( aout_thread_t *p_aout, aout_fifo_t *p_fifo ); aout_fifo_t *p_fifo );
void aout_DestroyFifo ( aout_fifo_t *p_fifo ); void aout_DestroyFifo ( aout_fifo_t *p_fifo );
void aout_FreeFifo ( aout_fifo_t *p_fifo );
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
*****************************************************************************/ *****************************************************************************/
/* Number of tries before we unload an unused module */ /* Number of tries before we unload an unused module */
#define MODULE_HIDE_DELAY 20 #define MODULE_HIDE_DELAY 100
/* The module handle type. */ /* The module handle type. */
#ifdef SYS_BEOS #ifdef SYS_BEOS
......
/*****************************************************************************
* aout_common.h: audio output inner functions
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
*
* Authors: Michel Kaempf <maxx@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.
*****************************************************************************/
/* Creating as many aout_Thread functions as configurations was one solution,
* examining the different cases in the Thread loop of an unique function was
* another. I chose the first solution. */
void aout_U8MonoThread ( aout_thread_t * p_aout );
void aout_U8StereoThread ( aout_thread_t * p_aout );
void aout_S8MonoThread ( aout_thread_t * p_aout );
void aout_S8StereoThread ( aout_thread_t * p_aout );
void aout_U16MonoThread ( aout_thread_t * p_aout );
void aout_U16StereoThread ( aout_thread_t * p_aout );
void aout_S16MonoThread ( aout_thread_t * p_aout );
void aout_S16StereoThread ( aout_thread_t * p_aout );
#define UPDATE_INCREMENT( increment, integer ) \
if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
{ \
(integer) += (increment).l_euclidean_integer + 1; \
(increment).l_remainder -= (increment).l_euclidean_denominator; \
} \
else \
{ \
(integer) += (increment).l_euclidean_integer; \
}
#define FIFO p_aout->fifo[i_fifo]
/*****************************************************************************
* InitializeIncrement
*****************************************************************************/
static __inline__ void InitializeIncrement( aout_increment_t * p_increment,
long l_numerator,
long l_denominator )
{
p_increment->l_remainder = -l_denominator;
p_increment->l_euclidean_integer = 0;
while ( l_numerator >= l_denominator )
{
p_increment->l_euclidean_integer++;
l_numerator -= l_denominator;
}
p_increment->l_euclidean_remainder = l_numerator;
p_increment->l_euclidean_denominator = l_denominator;
}
/*****************************************************************************
* NextFrame
*****************************************************************************/
static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo,
mtime_t aout_date )
{
long l_units, l_rate;
/* We take the lock */
vlc_mutex_lock( &p_fifo->data_lock );
/* Are we looking for a dated start frame ? */
if ( !p_fifo->b_start_frame )
{
while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
{
if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
{
p_fifo->b_start_frame = 1;
p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
break;
}
p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
}
if ( p_fifo->l_start_frame == p_fifo->l_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 ?? */
while ( !p_fifo->b_next_frame )
{
while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
{
if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
{
p_fifo->b_next_frame = 1;
break;
}
p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
}
while ( p_fifo->l_next_frame == p_fifo->l_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 );
}
}
}
l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
intf_DbgMsg( "aout debug: %lli (%li);", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->l_rate );
p_fifo->l_units = (((l_units - (p_fifo->l_unit -
(p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo)))))
* p_aout->l_rate) / l_rate) + 1;
/* We release the lock before leaving */
vlc_mutex_unlock( &p_fifo->data_lock );
return( 0 );
}
/*****************************************************************************
* aout_fifo.c : exported fifo management functions
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
*
* Authors: Michel Kaempf <maxx@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 "defs.h"
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h" /* mtime_t, mdate(), msleep() */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "audio_output.h"
#include "aout_common.h"
/*****************************************************************************
* aout_CreateFifo
*****************************************************************************/
aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
{
int i_fifo;
/* Take the fifos lock */
vlc_mutex_lock( &p_aout->fifos_lock );
/* Looking for a free fifo structure */
for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
{
if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
{
/* Not very clever, but at least we know which fifo it is */
p_aout->fifo[i_fifo].i_fifo = i_fifo;
break;
}
}
if ( i_fifo == AOUT_MAX_FIFOS )
{
intf_ErrMsg( "aout error: no fifo available" );
vlc_mutex_unlock( &p_aout->fifos_lock );
return( NULL );
}
/* Initialize the new fifo structure */
switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
{
case AOUT_INTF_MONO_FIFO:
case AOUT_INTF_STEREO_FIFO:
p_aout->fifo[i_fifo].b_die = 0;
p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
p_aout->fifo[i_fifo].l_unit = 0;
InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment,
p_fifo->l_rate, p_aout->l_rate );
p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
break;
case AOUT_ADEC_MONO_FIFO:
case AOUT_ADEC_STEREO_FIFO:
p_aout->fifo[i_fifo].b_die = 0;
p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
/* Allocate the memory needed to store the audio frames. 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_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size );
if ( p_aout->fifo[i_fifo].buffer == NULL )
{
intf_ErrMsg( "aout error: cannot create frame buffer" );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
vlc_mutex_unlock( &p_aout->fifos_lock );
return( NULL );
}
/* Allocate the memory needed to store the dates of the frames */
p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) );
if ( p_aout->fifo[i_fifo].date == NULL )
{
intf_ErrMsg( "aout error: cannot create date buffer");
free( p_aout->fifo[i_fifo].buffer );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
vlc_mutex_unlock( &p_aout->fifos_lock );
return( NULL );
}
/* 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_aout->fifo[i_fifo].l_start_frame = 0;
/* p_aout->fifo[i_fifo].l_next_frame = 0; */
p_aout->fifo[i_fifo].l_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_aout->fifo[i_fifo].b_start_frame = 0;
p_aout->fifo[i_fifo].b_next_frame = 0;
break;
default:
intf_ErrMsg( "aout error: unknown fifo type 0x%x", p_aout->fifo[i_fifo].i_type );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
vlc_mutex_unlock( &p_aout->fifos_lock );
return( NULL );
}
/* Release the fifos lock */
vlc_mutex_unlock( &p_aout->fifos_lock );
intf_WarnMsg( 2, "aout info: fifo #%i allocated, %i channels, rate %li",
p_aout->fifo[i_fifo].i_fifo, p_aout->fifo[i_fifo].i_channels, p_aout->fifo[i_fifo].l_rate );
/* Return the pointer to the fifo structure */
return( &FIFO );
}
/*****************************************************************************
* aout_DestroyFifo
*****************************************************************************/
void aout_DestroyFifo( aout_fifo_t * p_fifo )
{
intf_WarnMsg( 2, "aout info: fifo #%i destroyed", p_fifo->i_fifo );
p_fifo->b_die = 1;
}
/*****************************************************************************
* aout_FreeFifo
*****************************************************************************/
void aout_FreeFifo( aout_fifo_t * p_fifo )
{
switch ( p_fifo->i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
case AOUT_INTF_STEREO_FIFO:
free( p_fifo->buffer );
p_fifo->i_type = AOUT_EMPTY_FIFO;
break;
case AOUT_ADEC_MONO_FIFO:
case AOUT_ADEC_STEREO_FIFO:
free( p_fifo->buffer );
free( p_fifo->date );
p_fifo->i_type = AOUT_EMPTY_FIFO;
break;
default:
break;
}
}
/*****************************************************************************
* aout_s16.c: 16 bit signed audio output functions
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
*
* Authors: Michel Kaempf <maxx@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 "defs.h"
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h" /* mtime_t, mdate(), msleep() */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "audio_output.h"
#include "aout_common.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
/*****************************************************************************
* Functions
*****************************************************************************/
void aout_S16MonoThread( aout_thread_t * p_aout )
{
intf_ErrMsg( "aout error: 16 bit signed mono thread unsupported" );
}
void aout_S16StereoThread( aout_thread_t * p_aout )
{
int i_fifo;
long l_buffer, l_buffer_limit, l_bytes;
/* 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
{
S16StereoPlay( p_aout, &p_aout->fifo[i_fifo] );
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
{
((s16 *)p_aout->buffer)[l_buffer] = (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS ) * p_aout->vol / 256 ) ;
p_aout->s32_buffer[l_buffer] = 0;
}
l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
{
msleep( p_aout->l_msleep );
}
}
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 */
static void S16StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
{
long l_buffer = 0;
long l_buffer_limit, l_units;
switch ( p_fifo->i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
if ( p_fifo->l_units > p_aout->l_units )
{
/* p_aout->b_stereo == 1 */
while ( l_buffer < (p_aout->l_units << 1) )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
p_fifo->l_units -= p_aout->l_units;
}
else
{
/* p_aout->b_stereo == 1 */
while ( l_buffer < (p_fifo->l_units << 1) )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
free( p_fifo->buffer ); /* !! */
p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
}
break;
case AOUT_INTF_STEREO_FIFO:
if ( p_fifo->l_units > p_aout->l_units )
{
/* p_aout->b_stereo == 1 */
while ( l_buffer < (p_aout->l_units << 1) )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
p_fifo->l_units -= p_aout->l_units;
}
else
{
/* p_aout->b_stereo == 1 */
while ( l_buffer < (p_fifo->l_units << 1) )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
free( p_fifo->buffer );
p_fifo->i_type = AOUT_EMPTY_FIFO;
}
break;
case AOUT_ADEC_MONO_FIFO:
l_units = p_aout->l_units;
while ( l_units > 0 )
{
if ( !p_fifo->b_next_frame )
{
if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_fifo->l_units > l_units )
{
/* p_aout->b_stereo == 1 */
l_buffer_limit = p_aout->l_units << 1;
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
}
}
p_fifo->l_units -= l_units;
break;
}
else
{
/* p_aout->b_stereo == 1 */
l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
}
}
l_units -= p_fifo->l_units;
vlc_mutex_lock( &p_fifo->data_lock );
p_fifo->l_start_frame = p_fifo->l_next_frame;
vlc_cond_signal( &p_fifo->data_wait );
vlc_mutex_unlock( &p_fifo->data_lock );
/* p_fifo->b_start_frame = 1; */
p_fifo->l_next_frame += 1;
p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
p_fifo->b_next_frame = 0;
}
}
break;
case AOUT_ADEC_STEREO_FIFO:
l_units = p_aout->l_units;
while ( l_units > 0 )
{
if ( !p_fifo->b_next_frame )
{
if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_fifo->l_units > l_units )
{
/* p_aout->b_stereo == 1 */
l_buffer_limit = p_aout->l_units << 1;
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
}
}
p_fifo->l_units -= l_units;
break;
}
else
{
/* p_aout->b_stereo == 1 */
l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
}
}
l_units -= p_fifo->l_units;
vlc_mutex_lock( &p_fifo->data_lock );
p_fifo->l_start_frame = p_fifo->l_next_frame;
vlc_cond_signal( &p_fifo->data_wait );
vlc_mutex_unlock( &p_fifo->data_lock );
/* p_fifo->b_start_frame = 1; */
p_fifo->l_next_frame += 1;
p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
p_fifo->b_next_frame = 0;
}
}
break;
default:
intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
break;
}
}
/*****************************************************************************
* aout_s8.c: 8 bit signed audio output functions
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
*
* Authors: Michel Kaempf <maxx@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 "defs.h"
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h" /* mtime_t, mdate(), msleep() */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "audio_output.h"
#include "aout_common.h"
/*****************************************************************************
* Functions
*****************************************************************************/
void aout_S8MonoThread( aout_thread_t * p_aout )
{
intf_ErrMsg( "aout error: 8 bit signed mono thread unsupported" );
}
void aout_S8StereoThread( aout_thread_t * p_aout )
{
intf_ErrMsg( "aout error: 8 bit signed stereo thread unsupported" );
}
/*****************************************************************************
* aout_u16.c: 16 bit unsigned audio output functions
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
*
* Authors: Michel Kaempf <maxx@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 "defs.h"
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h" /* mtime_t, mdate(), msleep() */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "audio_output.h"
#include "aout_common.h"
/*****************************************************************************
* Functions
*****************************************************************************/
void aout_U16MonoThread( aout_thread_t * p_aout )
{
intf_ErrMsg( "aout error: 16 bit unsigned mono thread unsupported" );
}
void aout_U16StereoThread( aout_thread_t * p_aout )
{
intf_ErrMsg( "aout error: 16 bit unsigned stereo thread unsupported" );
}
/*****************************************************************************
* aout_u8.c: 8 bit unsigned audio output functions
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
*
* Authors: Michel Kaempf <maxx@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 "defs.h"
#include <stdio.h> /* "intf_msg.h" */
#include <stdlib.h> /* calloc(), malloc(), free() */
#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h" /* mtime_t, mdate(), msleep() */
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "audio_output.h"
#include "aout_common.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void U8MonoPlay ( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
static void U8StereoPlay ( aout_thread_t * p_aout, aout_fifo_t * p_fifo );
/*****************************************************************************
* Functions
*****************************************************************************/
void aout_U8MonoThread( aout_thread_t * p_aout )
{
int i_fifo;
long l_buffer, l_buffer_limit, l_bytes;
/* 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
{
U8MonoPlay( p_aout, &p_aout->fifo[i_fifo] );
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
{
((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256 ) + 128 ) * p_aout->vol / 256 );
p_aout->s32_buffer[l_buffer] = 0;
}
l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
p_aout->date = mdate() + ((((mtime_t)(l_bytes / 1 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 1 */
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
if ( l_bytes > (l_buffer_limit * sizeof(u8) * 2) ) /* There are 2 channels (left & right) */
{
msleep( p_aout->l_msleep );
}
}
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 );
}
void aout_U8StereoThread( aout_thread_t * p_aout )
{
int i_fifo;
long l_buffer, l_buffer_limit, l_bytes;
intf_DbgMsg("adec debug: running audio output U8_S_thread (%p) (pid == %i)", p_aout, getpid());
/* 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
{
U8StereoPlay( p_aout, &p_aout->fifo[i_fifo] );
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
l_buffer_limit = p_aout->l_units << 1 ; /* p_aout->b_stereo == 1 */
for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
{
((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256) + 128 ) * p_aout->vol / 256 );
p_aout->s32_buffer[l_buffer] = 0;
}
l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
p_aout->date = mdate() + ((((mtime_t)(l_bytes / 2 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 2 */
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
if ( l_bytes > (l_buffer_limit * sizeof(u8)) )
{
msleep( p_aout->l_msleep );
}
}
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 */
static void U8MonoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
{
long l_buffer = 0;
long l_buffer_limit, l_units;
switch ( p_fifo->i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
if ( p_fifo->l_units > p_aout->l_units )
{
/* p_aout->b_stereo == 0 */
while ( l_buffer < (p_aout->l_units) )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
p_fifo->l_units -= p_aout->l_units;
}
else
{
/* p_aout->b_stereo == 0 */
while ( l_buffer < (p_fifo->l_units) )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
free( p_fifo->buffer ); /* !! */
p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
}
break;
case AOUT_INTF_STEREO_FIFO:
if ( p_fifo->l_units > p_aout->l_units )
{
/* p_aout->b_stereo == 0 */
while ( l_buffer < (p_aout->l_units) )
{
/* I mix half left - half right */
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
p_fifo->l_units -= p_aout->l_units;
}
else
{
/* p_aout->b_stereo == 0 */
while ( l_buffer < (p_fifo->l_units) )
{
/* I mix half left - half right */
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
free( p_fifo->buffer ); /* !! */
p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
}
break;
case AOUT_ADEC_MONO_FIFO:
l_units = p_aout->l_units;
while ( l_units > 0 )
{
if ( !p_fifo->b_next_frame )
{
if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_fifo->l_units > l_units )
{
/* p_aout->b_stereo == 0 */
l_buffer_limit = p_aout->l_units;
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
}
}
p_fifo->l_units -= l_units;
break;
}
else
{
/* p_aout->b_stereo == 0 */
l_buffer_limit = l_buffer + (p_fifo->l_units);
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
}
}
l_units -= p_fifo->l_units;
vlc_mutex_lock( &p_fifo->data_lock );
p_fifo->l_start_frame = p_fifo->l_next_frame;
vlc_cond_signal( &p_fifo->data_wait );
vlc_mutex_unlock( &p_fifo->data_lock );
/* p_fifo->b_start_frame = 1; */
p_fifo->l_next_frame += 1;
p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
p_fifo->b_next_frame = 0;
}
}
break;
case AOUT_ADEC_STEREO_FIFO:
l_units = p_aout->l_units;
while ( l_units > 0 )
{
if ( !p_fifo->b_next_frame )
{
if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_fifo->l_units > l_units )
{
/* p_aout->b_stereo == 0 */
l_buffer_limit = p_aout->l_units;
while ( l_buffer < l_buffer_limit )
{
/* I mix half left - half right */
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
}
}
p_fifo->l_units -= l_units;
break;
}
else
{
/* p_aout->b_stereo == 0 */
l_buffer_limit = l_buffer + (p_fifo->l_units);
while ( l_buffer < l_buffer_limit )
{
/* I mix half left - half right */
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] ) / 2 +
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] ) / 2;
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
}
}
l_units -= p_fifo->l_units;
vlc_mutex_lock( &p_fifo->data_lock );
p_fifo->l_start_frame = p_fifo->l_next_frame;
vlc_cond_signal( &p_fifo->data_wait );
vlc_mutex_unlock( &p_fifo->data_lock );
/* p_fifo->b_start_frame = 1; */
p_fifo->l_next_frame += 1;
p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
p_fifo->b_next_frame = 0;
}
}
break;
default:
intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
break;
}
}
static void U8StereoPlay( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
{
long l_buffer = 0;
long l_buffer_limit, l_units;
switch ( p_fifo->i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
if ( p_fifo->l_units > p_aout->l_units )
{
while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
p_fifo->l_units -= p_aout->l_units;
}
else
{
while ( l_buffer < (p_fifo->l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
free( p_fifo->buffer ); /* !! */
p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
}
break;
case AOUT_INTF_STEREO_FIFO:
if ( p_fifo->l_units > p_aout->l_units )
{
while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
p_fifo->l_units -= p_aout->l_units;
}
else
{
while ( l_buffer < (p_fifo->l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
}
free( p_fifo->buffer ); /* !! */
p_fifo->i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", p_fifo); /* !! */
}
break;
case AOUT_ADEC_MONO_FIFO:
l_units = p_aout->l_units;
while ( l_units > 0 )
{
if ( !p_fifo->b_next_frame )
{
if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_fifo->l_units > l_units )
{
l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
}
}
p_fifo->l_units -= l_units;
break;
}
else
{
/* p_aout->b_stereo == 1 */
l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[p_fifo->l_unit] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 0));
}
}
l_units -= p_fifo->l_units;
vlc_mutex_lock( &p_fifo->data_lock );
p_fifo->l_start_frame = p_fifo->l_next_frame;
vlc_cond_signal( &p_fifo->data_wait );
vlc_mutex_unlock( &p_fifo->data_lock );
/* p_fifo->b_start_frame = 1; */
p_fifo->l_next_frame += 1;
p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
p_fifo->b_next_frame = 0;
}
}
break;
case AOUT_ADEC_STEREO_FIFO:
l_units = p_aout->l_units;
while ( l_units > 0 )
{
if ( !p_fifo->b_next_frame )
{
if ( NextFrame(p_aout, p_fifo, p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_fifo->l_units > l_units )
{
l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
}
}
p_fifo->l_units -= l_units;
break;
}
else
{
/* p_aout->b_stereo == 1 */
l_buffer_limit = l_buffer + (p_fifo->l_units << 1);
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_fifo->buffer)[2*p_fifo->l_unit+1] );
UPDATE_INCREMENT( p_fifo->unit_increment, p_fifo->l_unit )
if ( p_fifo->l_unit >= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1)) )
{
p_fifo->l_unit -= /* p_fifo->b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_fifo->l_frame_size >> 1));
}
}
l_units -= p_fifo->l_units;
vlc_mutex_lock( &p_fifo->data_lock );
p_fifo->l_start_frame = p_fifo->l_next_frame;
vlc_cond_signal( &p_fifo->data_wait );
vlc_mutex_unlock( &p_fifo->data_lock );
/* p_fifo->b_start_frame = 1; */
p_fifo->l_next_frame += 1;
p_fifo->l_next_frame &= AOUT_FIFO_SIZE;
p_fifo->b_next_frame = 0;
}
}
break;
default:
intf_DbgMsg("aout debug: unknown fifo type (%i)", p_fifo->i_type);
break;
}
}
/***************************************************************************** /*****************************************************************************
* audio_output.c : audio output thread * audio_output.c : audio output thread
***************************************************************************** *****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN * Copyright (C) 1999, 2000, 2001 VideoLAN
* *
* Authors: Michel Kaempf <maxx@via.ecp.fr> * Authors: Michel Kaempf <maxx@via.ecp.fr>
* *
...@@ -51,48 +51,15 @@ ...@@ -51,48 +51,15 @@
#include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */ #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
#include "audio_output.h" #include "audio_output.h"
#include "aout_common.h"
#include "main.h" #include "main.h"
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int aout_SpawnThread( aout_thread_t * p_aout ); static int aout_SpawnThread( aout_thread_t * p_aout );
/* Creating as much aout_Thread functions as configurations is one solution,
* examining the different cases in the Thread loop of an unique function is
* another. I chose the first solution. */
void aout_Thread_S8_Mono ( aout_thread_t * p_aout );
void aout_Thread_U8_Mono ( aout_thread_t * p_aout );
void aout_Thread_S16_Mono ( aout_thread_t * p_aout );
void aout_Thread_U16_Mono ( aout_thread_t * p_aout );
void aout_Thread_S8_Stereo ( aout_thread_t * p_aout );
void aout_Thread_U8_Stereo ( aout_thread_t * p_aout );
void aout_Thread_S16_Stereo ( aout_thread_t * p_aout );
void aout_Thread_U16_Stereo ( aout_thread_t * p_aout );
static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date );
/*****************************************************************************
* InitializeIncrement
*****************************************************************************/
static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
{
p_increment->l_remainder = -l_denominator;
p_increment->l_euclidean_integer = 0;
while ( l_numerator >= l_denominator )
{
p_increment->l_euclidean_integer++;
l_numerator -= l_denominator;
}
p_increment->l_euclidean_remainder = l_numerator;
p_increment->l_euclidean_denominator = l_denominator;
}
/***************************************************************************** /*****************************************************************************
* aout_CreateThread: initialize audio thread * aout_CreateThread: initialize audio thread
*****************************************************************************/ *****************************************************************************/
...@@ -185,8 +152,6 @@ static int aout_SpawnThread( aout_thread_t * p_aout ) ...@@ -185,8 +152,6 @@ static int aout_SpawnThread( aout_thread_t * p_aout )
long l_bytes; long l_bytes;
void * aout_thread = NULL; void * aout_thread = NULL;
intf_DbgMsg("aout debug: spawning audio output thread (%p)", p_aout);
/* We want the audio output thread to live */ /* We want the audio output thread to live */
p_aout->b_die = 0; p_aout->b_die = 0;
p_aout->b_active = 1; p_aout->b_active = 1;
...@@ -211,106 +176,118 @@ static int aout_SpawnThread( aout_thread_t * p_aout ) ...@@ -211,106 +176,118 @@ static int aout_SpawnThread( aout_thread_t * p_aout )
* byte size of the audio output buffer */ * byte size of the audio output buffer */
switch ( p_aout->i_channels ) switch ( p_aout->i_channels )
{ {
/* Audio output is mono */ /* Audio output is mono */
case 1: case 1:
switch ( p_aout->i_format ) switch ( p_aout->i_format )
{ {
case AOUT_FMT_U8: case AOUT_FMT_U8:
l_bytes = 1 * sizeof(u8) * p_aout->l_units; intf_WarnMsg( 2, "aout info: unsigned 8 bits mono thread" );
aout_thread = (void *)aout_Thread_U8_Mono; l_bytes = 1 * sizeof(u8) * p_aout->l_units;
break; aout_thread = (void *)aout_U8MonoThread;
break;
case AOUT_FMT_S8:
l_bytes = 1 * sizeof(s8) * p_aout->l_units;
aout_thread = (void *)aout_Thread_S8_Mono;
break;
case AOUT_FMT_U16_LE: case AOUT_FMT_S8:
case AOUT_FMT_U16_BE: intf_WarnMsg( 2, "aout info: signed 8 bits mono thread" );
l_bytes = 1 * sizeof(u16) * p_aout->l_units; l_bytes = 1 * sizeof(s8) * p_aout->l_units;
aout_thread = (void *)aout_Thread_U16_Mono; aout_thread = (void *)aout_S8MonoThread;
break; break;
case AOUT_FMT_S16_LE: case AOUT_FMT_U16_LE:
case AOUT_FMT_S16_BE: case AOUT_FMT_U16_BE:
l_bytes = 1 * sizeof(s16) * p_aout->l_units; intf_WarnMsg( 2, "aout info: unsigned 16 bits mono thread" );
aout_thread = (void *)aout_Thread_S16_Mono; l_bytes = 1 * sizeof(u16) * p_aout->l_units;
break; aout_thread = (void *)aout_U16MonoThread;
break;
default: case AOUT_FMT_S16_LE:
intf_ErrMsg( "aout error: unknown audio output format (%i)", case AOUT_FMT_S16_BE:
p_aout->i_format ); intf_WarnMsg( 2, "aout info: signed 16 bits mono thread" );
return( -1 ); l_bytes = 1 * sizeof(s16) * p_aout->l_units;
} aout_thread = (void *)aout_S16MonoThread;
break; break;
/* Audio output is stereo */ default:
case 2: intf_ErrMsg( "aout error: unknown audio output format (%i)",
switch ( p_aout->i_format ) p_aout->i_format );
{ return( -1 );
case AOUT_FMT_U8: }
l_bytes = 2 * sizeof(u8) * p_aout->l_units; break;
aout_thread = (void *)aout_Thread_U8_Stereo;
break;
case AOUT_FMT_S8: /* Audio output is stereo */
l_bytes = 2 * sizeof(s8) * p_aout->l_units; case 2:
aout_thread = (void *)aout_Thread_S8_Stereo; switch ( p_aout->i_format )
break; {
case AOUT_FMT_U8:
intf_WarnMsg( 2, "aout info: unsigned 8 bits stereo thread" );
l_bytes = 2 * sizeof(u8) * p_aout->l_units;
aout_thread = (void *)aout_U8StereoThread;
break;
case AOUT_FMT_U16_LE: case AOUT_FMT_S8:
case AOUT_FMT_U16_BE: intf_WarnMsg( 2, "aout info: signed 8 bits stereo thread" );
l_bytes = 2 * sizeof(u16) * p_aout->l_units; l_bytes = 2 * sizeof(s8) * p_aout->l_units;
aout_thread = (void *)aout_Thread_U16_Stereo; aout_thread = (void *)aout_S8StereoThread;
break; break;
case AOUT_FMT_S16_LE: case AOUT_FMT_U16_LE:
case AOUT_FMT_S16_BE: case AOUT_FMT_U16_BE:
l_bytes = 2 * sizeof(s16) * p_aout->l_units; intf_WarnMsg( 2, "aout info: unsigned 16 bits stereo thread" );
aout_thread = (void *)aout_Thread_S16_Stereo; l_bytes = 2 * sizeof(u16) * p_aout->l_units;
break; aout_thread = (void *)aout_U16StereoThread;
break;
default: case AOUT_FMT_S16_LE:
intf_ErrMsg("aout error: unknown audio output format (%i)", case AOUT_FMT_S16_BE:
p_aout->i_format); intf_WarnMsg( 2, "aout info: signed 16 bits stereo thread" );
return( -1 ); l_bytes = 2 * sizeof(s16) * p_aout->l_units;
} aout_thread = (void *)aout_S16StereoThread;
break; break;
default: default:
intf_ErrMsg("aout error: unknown number of audio channels (%i)", intf_ErrMsg( "aout error: unknown audio output format %i",
p_aout->i_channels ); p_aout->i_format );
return( -1 ); return( -1 );
}
break;
default:
intf_ErrMsg( "aout error: unknown number of audio channels (%i)",
p_aout->i_channels );
return( -1 );
} }
/* Allocate the memory needed by the audio output buffers, and set to zero /* Allocate the memory needed by the audio output buffers, and set to zero
* the s32 buffer's memory */ * the s32 buffer's memory */
if ( (p_aout->buffer = malloc(l_bytes)) == NULL ) p_aout->buffer = malloc( l_bytes );
if ( p_aout->buffer == NULL )
{ {
intf_ErrMsg("aout error: not enough memory to create the output buffer"); intf_ErrMsg( "aout error: cannot create output buffer" );
return( -1 ); return( -1 );
} }
if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << ( p_aout->b_stereo))) == NULL )
p_aout->s32_buffer = (s32 *)calloc( p_aout->l_units,
sizeof(s32) << ( p_aout->b_stereo ) );
if ( p_aout->s32_buffer == NULL )
{ {
intf_ErrMsg("aout error: not enough memory to create the s32 output buffer"); intf_ErrMsg( "aout error: cannot create the s32 output buffer" );
free( p_aout->buffer ); free( p_aout->buffer );
return( -1 ); return( -1 );
} }
/* Before launching the thread, we try to predict the date of the first /* Rough estimate of the playing date */
* audio unit in the first output buffer */ p_aout->date = mdate();
p_aout->date = mdate() - 1000000;
/* Launch the thread */ /* Launch the thread */
if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) ) if ( vlc_thread_create( &p_aout->thread_id, "audio output",
(vlc_thread_func_t)aout_thread, p_aout ) )
{ {
intf_ErrMsg("aout error: can't spawn audio output thread (%p)", p_aout); intf_ErrMsg( "aout error: cannot spawn audio output thread" );
free( p_aout->buffer ); free( p_aout->buffer );
free( p_aout->s32_buffer ); free( p_aout->s32_buffer );
return( -1 ); return( -1 );
} }
intf_DbgMsg("aout debug: audio output thread (%p) spawned", p_aout); intf_WarnMsg( 2, "aout info: audio output thread %i spawned", getpid() );
return( 0 ); return( 0 );
} }
...@@ -324,8 +301,6 @@ void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status ) ...@@ -324,8 +301,6 @@ void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
/* FIXME: pi_status is not handled correctly: check vout how to do!?? */ /* FIXME: pi_status is not handled correctly: check vout how to do!?? */
intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)", p_aout);
/* Ask thread to kill itself and wait until it's done */ /* Ask thread to kill itself and wait until it's done */
p_aout->b_die = 1; p_aout->b_die = 1;
vlc_thread_join( p_aout->thread_id ); /* only if pi_status is NULL */ vlc_thread_join( p_aout->thread_id ); /* only if pi_status is NULL */
...@@ -352,1087 +327,3 @@ void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status ) ...@@ -352,1087 +327,3 @@ void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
free( p_aout ); free( p_aout );
} }
/*****************************************************************************
* aout_CreateFifo
*****************************************************************************/
aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
{
int i_fifo;
/* Take the fifos lock */
vlc_mutex_lock( &p_aout->fifos_lock );
/* Looking for a free fifo structure */
for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
{
if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
{
break;
}
}
if ( i_fifo == AOUT_MAX_FIFOS )
{
intf_ErrMsg("aout error: no empty fifo available");
vlc_mutex_unlock( &p_aout->fifos_lock );
return( NULL );
}
/* Initialize the new fifo structure */
switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
{
case AOUT_INTF_MONO_FIFO:
case AOUT_INTF_STEREO_FIFO:
p_aout->fifo[i_fifo].b_die = 0;
p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
p_aout->fifo[i_fifo].l_unit = 0;
InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->l_rate );
p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
break;
case AOUT_ADEC_MONO_FIFO:
case AOUT_ADEC_STEREO_FIFO:
p_aout->fifo[i_fifo].b_die = 0;
p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
/* Allocate the memory needed to store the audio frames. 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. */
if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
{
intf_ErrMsg("aout error: not enough memory to create the frames buffer");
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
vlc_mutex_unlock( &p_aout->fifos_lock );
return( NULL );
}
/* Allocate the memory needed to store the dates of the frames */
if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
{
intf_ErrMsg("aout error: not enough memory to create the dates buffer");
free( p_aout->fifo[i_fifo].buffer );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
vlc_mutex_unlock( &p_aout->fifos_lock );
return( NULL );
}
/* 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_aout->fifo[i_fifo].l_start_frame = 0;
/* p_aout->fifo[i_fifo].l_next_frame = 0; */
p_aout->fifo[i_fifo].l_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_aout->fifo[i_fifo].b_start_frame = 0;
p_aout->fifo[i_fifo].b_next_frame = 0;
break;
default:
intf_ErrMsg("aout error: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
vlc_mutex_unlock( &p_aout->fifos_lock );
return( NULL );
}
/* Release the fifos lock */
vlc_mutex_unlock( &p_aout->fifos_lock );
/* Return the pointer to the fifo structure */
intf_DbgMsg("aout debug: audio output fifo (%p) allocated", &p_aout->fifo[i_fifo]);
return( &p_aout->fifo[i_fifo] );
}
/*****************************************************************************
* aout_DestroyFifo
*****************************************************************************/
void aout_DestroyFifo( aout_fifo_t * p_fifo )
{
intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)", p_fifo);
p_fifo->b_die = 1;
}
/* Here are the local macros */
#define UPDATE_INCREMENT( increment, integer ) \
if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
{ \
(integer) += (increment).l_euclidean_integer + 1; \
(increment).l_remainder -= (increment).l_euclidean_denominator; \
} \
else \
{ \
(integer) += (increment).l_euclidean_integer; \
}
/* Following functions are local */
/*****************************************************************************
* NextFrame
*****************************************************************************/
static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date )
{
long l_units, l_rate;
/* We take the lock */
vlc_mutex_lock( &p_fifo->data_lock );
/* Are we looking for a dated start frame ? */
if ( !p_fifo->b_start_frame )
{
while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
{
if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
{
p_fifo->b_start_frame = 1;
p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
break;
}
p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
}
if ( p_fifo->l_start_frame == p_fifo->l_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 ?? */
while ( !p_fifo->b_next_frame )
{
while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
{
if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
{
p_fifo->b_next_frame = 1;
break;
}
p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
}
while ( p_fifo->l_next_frame == p_fifo->l_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 );
}
}
}
l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
intf_DbgMsg( "aout debug: %lli (%li);", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->l_rate );
p_fifo->l_units = (((l_units - (p_fifo->l_unit -
(p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo)))))
* p_aout->l_rate) / l_rate) + 1;
/* We release the lock before leaving */
vlc_mutex_unlock( &p_fifo->data_lock );
return( 0 );
}
void aout_Thread_S8_Mono( aout_thread_t * p_aout )
{
}
void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
{
}
void aout_Thread_U8_Mono( aout_thread_t * p_aout )
{
int i_fifo;
long l_buffer, l_buffer_limit;
long l_units, l_bytes;
intf_DbgMsg("adec debug: running audio output U8_M_thread (%p) (pid == %i)", p_aout, getpid());
/* 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++ )
{
switch ( p_aout->fifo[i_fifo].i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
{
l_buffer = 0;
while ( l_buffer < (p_aout->l_units) ) /* p_aout->b_stereo == 0 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
}
else
{
l_buffer = 0;
while ( l_buffer < (p_aout->fifo[i_fifo].l_units) ) /* p_aout->b_stereo == 0 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
}
break;
case AOUT_INTF_STEREO_FIFO:
if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
{
l_buffer = 0;
while ( l_buffer < (p_aout->l_units) ) /* p_aout->b_stereo == 0 */
{
/* I mix half left - half right */
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
}
else
{
l_buffer = 0;
while ( l_buffer < (p_aout->fifo[i_fifo].l_units) ) /* p_aout->b_stereo == 0 */
{
/* I mix half left - half right */
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
}
break;
case AOUT_ADEC_MONO_FIFO:
if ( p_aout->fifo[i_fifo].b_die )
{
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
continue;
}
l_units = p_aout->l_units;
l_buffer = 0;
while ( l_units > 0 )
{
if ( !p_aout->fifo[i_fifo].b_next_frame )
{
if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_aout->fifo[i_fifo].l_units > l_units )
{
l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
}
}
p_aout->fifo[i_fifo].l_units -= l_units;
break;
}
else
{
l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units);
/* p_aout->b_stereo == 0 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
}
}
l_units -= p_aout->fifo[i_fifo].l_units;
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/* p_aout->fifo[i_fifo].b_start_frame = 1; */
p_aout->fifo[i_fifo].l_next_frame += 1;
p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
p_aout->fifo[i_fifo].b_next_frame = 0;
}
}
break;
case AOUT_ADEC_STEREO_FIFO:
if ( p_aout->fifo[i_fifo].b_die )
{
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
continue;
}
l_units = p_aout->l_units;
l_buffer = 0;
while ( l_units > 0 )
{
if ( !p_aout->fifo[i_fifo].b_next_frame )
{
if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_aout->fifo[i_fifo].l_units > l_units )
{
l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
while ( l_buffer < l_buffer_limit )
{
/* I mix half left - half right */
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
}
}
p_aout->fifo[i_fifo].l_units -= l_units;
break;
}
else
{
l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units);
/* p_aout->b_stereo == 0 */
while ( l_buffer < l_buffer_limit )
{
/* I mix half left - half right */
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
}
}
l_units -= p_aout->fifo[i_fifo].l_units;
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/* p_aout->fifo[i_fifo].b_start_frame = 1; */
p_aout->fifo[i_fifo].l_next_frame += 1;
p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
p_aout->fifo[i_fifo].b_next_frame = 0;
}
}
break;
default:
intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
break;
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
{
((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256 ) + 128 ) * p_aout->vol / 256 );
p_aout->s32_buffer[l_buffer] = 0;
}
l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
p_aout->date = mdate() + ((((mtime_t)(l_bytes / 1 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 1 */
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
if ( l_bytes > (l_buffer_limit * sizeof(u8) * 2) ) /* There are 2 channels (left & right) */
{
msleep( p_aout->l_msleep );
}
}
vlc_mutex_lock( &p_aout->fifos_lock );
for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
{
switch ( p_aout->fifo[i_fifo].i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
case AOUT_INTF_STEREO_FIFO:
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
break;
case AOUT_ADEC_MONO_FIFO:
case AOUT_ADEC_STEREO_FIFO:
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
break;
default:
break;
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
}
void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
{
int i_fifo;
long l_buffer, l_buffer_limit;
long l_units, l_bytes;
intf_DbgMsg("adec debug: running audio output U8_S_thread (%p) (pid == %i)", p_aout, getpid());
/* 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++ )
{
switch ( p_aout->fifo[i_fifo].i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
{
l_buffer = 0;
while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
}
else
{
l_buffer = 0;
while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
}
break;
case AOUT_INTF_STEREO_FIFO:
if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
{
l_buffer = 0;
while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
}
else
{
l_buffer = 0;
while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
}
break;
case AOUT_ADEC_MONO_FIFO:
if ( p_aout->fifo[i_fifo].b_die )
{
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
continue;
}
l_units = p_aout->l_units;
l_buffer = 0;
while ( l_units > 0 )
{
if ( !p_aout->fifo[i_fifo].b_next_frame )
{
if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_aout->fifo[i_fifo].l_units > l_units )
{
l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
}
}
p_aout->fifo[i_fifo].l_units -= l_units;
break;
}
else
{
l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
/* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
}
}
l_units -= p_aout->fifo[i_fifo].l_units;
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/* p_aout->fifo[i_fifo].b_start_frame = 1; */
p_aout->fifo[i_fifo].l_next_frame += 1;
p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
p_aout->fifo[i_fifo].b_next_frame = 0;
}
}
break;
case AOUT_ADEC_STEREO_FIFO:
if ( p_aout->fifo[i_fifo].b_die )
{
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
continue;
}
l_units = p_aout->l_units;
l_buffer = 0;
while ( l_units > 0 )
{
if ( !p_aout->fifo[i_fifo].b_next_frame )
{
if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_aout->fifo[i_fifo].l_units > l_units )
{
l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
}
}
p_aout->fifo[i_fifo].l_units -= l_units;
break;
}
else
{
l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
/* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
}
}
l_units -= p_aout->fifo[i_fifo].l_units;
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/* p_aout->fifo[i_fifo].b_start_frame = 1; */
p_aout->fifo[i_fifo].l_next_frame += 1;
p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
p_aout->fifo[i_fifo].b_next_frame = 0;
}
}
break;
default:
intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
break;
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
l_buffer_limit = p_aout->l_units << 1 ; /* p_aout->b_stereo == 1 */
for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
{
((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256) + 128 ) * p_aout->vol / 256 );
p_aout->s32_buffer[l_buffer] = 0;
}
l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
p_aout->date = mdate() + ((((mtime_t)(l_bytes / 2 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 2 */
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
if ( l_bytes > (l_buffer_limit * sizeof(u8)) )
{
msleep( p_aout->l_msleep );
}
}
vlc_mutex_lock( &p_aout->fifos_lock );
for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
{
switch ( p_aout->fifo[i_fifo].i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
case AOUT_INTF_STEREO_FIFO:
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
break;
case AOUT_ADEC_MONO_FIFO:
case AOUT_ADEC_STEREO_FIFO:
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
break;
default:
break;
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
}
void aout_Thread_S16_Mono( aout_thread_t * p_aout )
{
}
void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
{
int i_fifo;
long l_buffer, l_buffer_limit;
long l_units, l_bytes;
intf_DbgMsg("adec debug: running audio output S16_S_thread (%p) (pid == %i)", p_aout, getpid());
/* 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++ )
{
switch ( p_aout->fifo[i_fifo].i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
{
l_buffer = 0;
while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
}
else
{
l_buffer = 0;
while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
}
break;
case AOUT_INTF_STEREO_FIFO:
if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
{
l_buffer = 0;
while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
}
else
{
l_buffer = 0;
while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
}
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
}
break;
case AOUT_ADEC_MONO_FIFO:
if ( p_aout->fifo[i_fifo].b_die )
{
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
continue;
}
l_units = p_aout->l_units;
l_buffer = 0;
while ( l_units > 0 )
{
if ( !p_aout->fifo[i_fifo].b_next_frame )
{
if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_aout->fifo[i_fifo].l_units > l_units )
{
l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
}
}
p_aout->fifo[i_fifo].l_units -= l_units;
break;
}
else
{
l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
/* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
}
}
l_units -= p_aout->fifo[i_fifo].l_units;
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/* p_aout->fifo[i_fifo].b_start_frame = 1; */
p_aout->fifo[i_fifo].l_next_frame += 1;
p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
p_aout->fifo[i_fifo].b_next_frame = 0;
}
}
break;
case AOUT_ADEC_STEREO_FIFO:
if ( p_aout->fifo[i_fifo].b_die )
{
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
continue;
}
l_units = p_aout->l_units;
l_buffer = 0;
while ( l_units > 0 )
{
if ( !p_aout->fifo[i_fifo].b_next_frame )
{
if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
{
break;
}
}
if ( p_aout->fifo[i_fifo].l_units > l_units )
{
l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
}
}
p_aout->fifo[i_fifo].l_units -= l_units;
break;
}
else
{
l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
/* p_aout->b_stereo == 1 */
while ( l_buffer < l_buffer_limit )
{
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
p_aout->s32_buffer[l_buffer++] +=
(s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
{
p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
}
}
l_units -= p_aout->fifo[i_fifo].l_units;
vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
/* p_aout->fifo[i_fifo].b_start_frame = 1; */
p_aout->fifo[i_fifo].l_next_frame += 1;
p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
p_aout->fifo[i_fifo].b_next_frame = 0;
}
}
break;
default:
intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
break;
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
{
((s16 *)p_aout->buffer)[l_buffer] = (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS ) * p_aout->vol / 256 ) ;
p_aout->s32_buffer[l_buffer] = 0;
}
l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
{
msleep( p_aout->l_msleep );
}
}
vlc_mutex_lock( &p_aout->fifos_lock );
for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
{
switch ( p_aout->fifo[i_fifo].i_type )
{
case AOUT_EMPTY_FIFO:
break;
case AOUT_INTF_MONO_FIFO:
case AOUT_INTF_STEREO_FIFO:
free( p_aout->fifo[i_fifo].buffer ); /* !! */
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
break;
case AOUT_ADEC_MONO_FIFO:
case AOUT_ADEC_STEREO_FIFO:
free( p_aout->fifo[i_fifo].buffer );
free( p_aout->fifo[i_fifo].date );
p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
break;
default:
break;
}
}
vlc_mutex_unlock( &p_aout->fifos_lock );
}
void aout_Thread_U16_Mono( aout_thread_t * p_aout )
{
}
void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
{
}
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