1 /*****************************************************************************
2 * aout_ext-dec.c : exported fifo management functions
3 *****************************************************************************
4 * Copyright (C) 1999-2001 VideoLAN
5 * $Id: aout_ext-dec.c,v 1.10 2002/01/14 12:15:10 asmax Exp $
7 * Authors: Michel Kaempf <maxx@via.ecp.fr>
8 * Cyril Deguet <asmax@via.ecp.fr>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdio.h> /* "intf_msg.h" */
29 #include <stdlib.h> /* calloc(), malloc(), free() */
32 #include <videolan/vlc.h>
34 #include "audio_output.h"
35 #include "aout_common.h"
37 /*****************************************************************************
39 *****************************************************************************/
40 aout_fifo_t * aout_CreateFifo( int i_type, int i_channels, long l_rate,
41 long l_units, long l_frame_size,
44 aout_thread_t *p_aout;
47 /* Spawn an audio output if there is none */
48 vlc_mutex_lock( &p_aout_bank->lock );
50 if( p_aout_bank->i_count == 0 )
52 intf_WarnMsg( 1, "aout: no aout present, spawning one" );
54 p_aout = aout_CreateThread( NULL, i_channels, l_rate );
56 /* Everything failed */
59 vlc_mutex_unlock( &p_aout_bank->lock );
63 p_aout_bank->pp_aout[ p_aout_bank->i_count ] = p_aout;
64 p_aout_bank->i_count++;
66 /* temporary hack to switch output type (mainly for spdif)
67 * FIXME: to be adapted when several output are available */
68 else if( p_aout_bank->pp_aout[0]->fifo[0].i_type != i_type )
70 intf_WarnMsg( 1, "aout: changing aout type" );
72 aout_DestroyThread( p_aout_bank->pp_aout[0], NULL );
74 p_aout = aout_CreateThread( NULL, i_channels, l_rate );
76 /* Everything failed */
79 vlc_mutex_unlock( &p_aout_bank->lock );
83 p_aout_bank->pp_aout[0] = p_aout;
88 /* Take the first audio output FIXME: take the best one */
89 p_aout = p_aout_bank->pp_aout[ 0 ];
92 /* Take the fifos lock */
93 vlc_mutex_lock( &p_aout->fifos_lock );
95 /* Looking for a free fifo structure */
96 for( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
98 if( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO )
100 /* Not very clever, but at least we know which fifo it is */
101 p_aout->fifo[i_fifo].i_fifo = i_fifo;
106 if( i_fifo == AOUT_MAX_FIFOS )
108 intf_ErrMsg( "aout error: no fifo available" );
109 vlc_mutex_unlock( &p_aout->fifos_lock );
110 vlc_mutex_unlock( &p_aout_bank->lock );
114 /* Initialize the new fifo structure */
115 switch ( p_aout->fifo[i_fifo].i_type = i_type )
117 case AOUT_ADEC_MONO_FIFO:
118 case AOUT_ADEC_STEREO_FIFO:
119 case AOUT_ADEC_SPDIF_FIFO:
120 p_aout->fifo[i_fifo].b_die = 0;
122 p_aout->fifo[i_fifo].i_channels = i_channels;
123 p_aout->fifo[i_fifo].b_stereo = ( i_channels == 2 );
124 p_aout->fifo[i_fifo].l_rate = l_rate;
126 p_aout->fifo[i_fifo].l_frame_size = l_frame_size;
127 /* Allocate the memory needed to store the audio frames. As the
128 * fifo is a rotative fifo, we must be able to find out whether
129 * the fifo is full or empty, that's why we must in fact allocate
130 * memory for (AOUT_FIFO_SIZE+1) audio frames. */
131 p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16) *
132 ( AOUT_FIFO_SIZE + 1 ) * l_frame_size );
133 if ( p_aout->fifo[i_fifo].buffer == NULL )
135 intf_ErrMsg( "aout error: cannot create frame buffer" );
136 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
137 vlc_mutex_unlock( &p_aout->fifos_lock );
138 vlc_mutex_unlock( &p_aout_bank->lock );
142 /* Allocate the memory needed to store the dates of the frames */
143 p_aout->fifo[i_fifo].date =
144 malloc( sizeof(mtime_t) * ( AOUT_FIFO_SIZE + 1) );
146 if ( p_aout->fifo[i_fifo].date == NULL )
148 intf_ErrMsg( "aout error: cannot create date buffer");
149 free( p_aout->fifo[i_fifo].buffer );
150 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
151 vlc_mutex_unlock( &p_aout->fifos_lock );
152 vlc_mutex_unlock( &p_aout_bank->lock );
156 /* Set the fifo's buffer as empty (the first frame that is to be
157 * played is also the first frame that is not to be played) */
158 p_aout->fifo[i_fifo].l_start_frame = 0;
159 /* p_aout->fifo[i_fifo].l_next_frame = 0; */
160 p_aout->fifo[i_fifo].l_end_frame = 0;
162 /* Waiting for the audio decoder to compute enough frames to work
163 * out the fifo's current rate (as soon as the decoder has decoded
164 * enough frames, the members of the fifo structure that are not
165 * initialized now will be calculated) */
166 p_aout->fifo[i_fifo].b_start_frame = 0;
167 p_aout->fifo[i_fifo].b_next_frame = 0;
171 intf_ErrMsg( "aout error: unknown fifo type 0x%x",
172 p_aout->fifo[i_fifo].i_type );
173 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
174 vlc_mutex_unlock( &p_aout->fifos_lock );
175 vlc_mutex_unlock( &p_aout_bank->lock );
179 /* Release the fifos lock */
180 vlc_mutex_unlock( &p_aout->fifos_lock );
181 vlc_mutex_unlock( &p_aout_bank->lock );
183 intf_WarnMsg( 2, "aout info: fifo #%i allocated, %i channels, rate %li",
184 p_aout->fifo[i_fifo].i_fifo, p_aout->fifo[i_fifo].i_channels,
185 p_aout->fifo[i_fifo].l_rate );
187 /* Return the pointer to the fifo structure */
188 return( &p_aout->fifo[i_fifo] );
191 /*****************************************************************************
193 *****************************************************************************/
194 void aout_DestroyFifo( aout_fifo_t * p_fifo )
196 intf_WarnMsg( 2, "aout info: fifo #%i destroyed", p_fifo->i_fifo );
201 /*****************************************************************************
203 *****************************************************************************/
204 void aout_FreeFifo( aout_fifo_t * p_fifo )
206 switch ( p_fifo->i_type )
208 case AOUT_EMPTY_FIFO:
212 case AOUT_ADEC_MONO_FIFO:
213 case AOUT_ADEC_STEREO_FIFO:
214 case AOUT_ADEC_SPDIF_FIFO:
216 free( p_fifo->buffer );
217 free( p_fifo->date );
218 p_fifo->i_type = AOUT_EMPTY_FIFO;