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.8 2001/12/30 07:09:56 sam Exp $
7 * Authors: Michel Kaempf <maxx@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
27 #include <stdio.h> /* "intf_msg.h" */
28 #include <stdlib.h> /* calloc(), malloc(), free() */
31 #include <videolan/vlc.h>
33 #include "audio_output.h"
34 #include "aout_common.h"
36 /*****************************************************************************
38 *****************************************************************************/
39 aout_fifo_t * aout_CreateFifo( int i_type, int i_channels, long l_rate,
40 long l_units, long l_frame_size,
43 aout_thread_t *p_aout;
46 /* Spawn an audio output if there is none */
47 vlc_mutex_lock( &p_aout_bank->lock );
49 if( p_aout_bank->i_count == 0 )
51 intf_WarnMsg( 1, "aout: no aout present, spawning one" );
53 p_aout = aout_CreateThread( NULL );
55 /* Everything failed */
58 vlc_mutex_unlock( &p_aout_bank->lock );
62 p_aout_bank->pp_aout[ p_aout_bank->i_count ] = p_aout;
63 p_aout_bank->i_count++;
65 /* temporary hack to switch output type (mainly for spdif)
66 * FIXME: to be adapted when several output are available */
67 else if( p_aout_bank->pp_aout[0]->fifo[0].i_type != i_type )
69 intf_WarnMsg( 1, "aout: changing aout type" );
71 aout_DestroyThread( p_aout_bank->pp_aout[0], NULL );
73 p_aout = aout_CreateThread( NULL );
75 /* Everything failed */
78 vlc_mutex_unlock( &p_aout_bank->lock );
82 p_aout_bank->pp_aout[0] = p_aout;
87 /* Take the first audio output FIXME: take the best one */
88 p_aout = p_aout_bank->pp_aout[ 0 ];
91 /* Take the fifos lock */
92 vlc_mutex_lock( &p_aout->fifos_lock );
94 /* Looking for a free fifo structure */
95 for( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
97 if( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO )
99 /* Not very clever, but at least we know which fifo it is */
100 p_aout->fifo[i_fifo].i_fifo = i_fifo;
105 if( i_fifo == AOUT_MAX_FIFOS )
107 intf_ErrMsg( "aout error: no fifo available" );
108 vlc_mutex_unlock( &p_aout->fifos_lock );
109 vlc_mutex_unlock( &p_aout_bank->lock );
113 /* Initialize the new fifo structure */
114 switch ( p_aout->fifo[i_fifo].i_type = i_type )
116 case AOUT_INTF_MONO_FIFO:
117 case AOUT_INTF_STEREO_FIFO:
118 p_aout->fifo[i_fifo].b_die = 0;
120 p_aout->fifo[i_fifo].i_channels = i_channels;
121 p_aout->fifo[i_fifo].b_stereo = ( i_channels == 2 );
122 p_aout->fifo[i_fifo].l_rate = l_rate;
124 p_aout->fifo[i_fifo].buffer = p_buffer;
126 p_aout->fifo[i_fifo].l_unit = 0;
127 InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment,
128 l_rate, p_aout->l_rate );
129 p_aout->fifo[i_fifo].l_units = l_units;
132 case AOUT_ADEC_MONO_FIFO:
133 case AOUT_ADEC_STEREO_FIFO:
134 case AOUT_ADEC_SPDIF_FIFO:
135 p_aout->fifo[i_fifo].b_die = 0;
137 p_aout->fifo[i_fifo].i_channels = i_channels;
138 p_aout->fifo[i_fifo].b_stereo = ( i_channels == 2 );
139 p_aout->fifo[i_fifo].l_rate = l_rate;
141 p_aout->fifo[i_fifo].l_frame_size = l_frame_size;
142 /* Allocate the memory needed to store the audio frames. As the
143 * fifo is a rotative fifo, we must be able to find out whether
144 * the fifo is full or empty, that's why we must in fact allocate
145 * memory for (AOUT_FIFO_SIZE+1) audio frames. */
146 p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16) *
147 ( AOUT_FIFO_SIZE + 1 ) * l_frame_size );
148 if ( p_aout->fifo[i_fifo].buffer == NULL )
150 intf_ErrMsg( "aout error: cannot create frame buffer" );
151 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
152 vlc_mutex_unlock( &p_aout->fifos_lock );
153 vlc_mutex_unlock( &p_aout_bank->lock );
157 /* Allocate the memory needed to store the dates of the frames */
158 p_aout->fifo[i_fifo].date =
159 malloc( sizeof(mtime_t) * ( AOUT_FIFO_SIZE + 1) );
161 if ( p_aout->fifo[i_fifo].date == NULL )
163 intf_ErrMsg( "aout error: cannot create date buffer");
164 free( p_aout->fifo[i_fifo].buffer );
165 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
166 vlc_mutex_unlock( &p_aout->fifos_lock );
167 vlc_mutex_unlock( &p_aout_bank->lock );
171 /* Set the fifo's buffer as empty (the first frame that is to be
172 * played is also the first frame that is not to be played) */
173 p_aout->fifo[i_fifo].l_start_frame = 0;
174 /* p_aout->fifo[i_fifo].l_next_frame = 0; */
175 p_aout->fifo[i_fifo].l_end_frame = 0;
177 /* Waiting for the audio decoder to compute enough frames to work
178 * out the fifo's current rate (as soon as the decoder has decoded
179 * enough frames, the members of the fifo structure that are not
180 * initialized now will be calculated) */
181 p_aout->fifo[i_fifo].b_start_frame = 0;
182 p_aout->fifo[i_fifo].b_next_frame = 0;
186 intf_ErrMsg( "aout error: unknown fifo type 0x%x",
187 p_aout->fifo[i_fifo].i_type );
188 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
189 vlc_mutex_unlock( &p_aout->fifos_lock );
190 vlc_mutex_unlock( &p_aout_bank->lock );
194 /* Release the fifos lock */
195 vlc_mutex_unlock( &p_aout->fifos_lock );
196 vlc_mutex_unlock( &p_aout_bank->lock );
198 intf_WarnMsg( 2, "aout info: fifo #%i allocated, %i channels, rate %li",
199 p_aout->fifo[i_fifo].i_fifo, p_aout->fifo[i_fifo].i_channels,
200 p_aout->fifo[i_fifo].l_rate );
202 /* Return the pointer to the fifo structure */
203 return( &p_aout->fifo[i_fifo] );
206 /*****************************************************************************
208 *****************************************************************************/
209 void aout_DestroyFifo( aout_fifo_t * p_fifo )
211 intf_WarnMsg( 2, "aout info: fifo #%i destroyed", p_fifo->i_fifo );
216 /*****************************************************************************
218 *****************************************************************************/
219 void aout_FreeFifo( aout_fifo_t * p_fifo )
221 switch ( p_fifo->i_type )
223 case AOUT_EMPTY_FIFO:
227 case AOUT_INTF_MONO_FIFO:
228 case AOUT_INTF_STEREO_FIFO:
230 free( p_fifo->buffer );
231 p_fifo->i_type = AOUT_EMPTY_FIFO;
235 case AOUT_ADEC_MONO_FIFO:
236 case AOUT_ADEC_STEREO_FIFO:
237 case AOUT_ADEC_SPDIF_FIFO:
239 free( p_fifo->buffer );
240 free( p_fifo->date );
241 p_fifo->i_type = AOUT_EMPTY_FIFO;