1 /*****************************************************************************
2 * aout_ext-dec.c : exported fifo management functions
3 *****************************************************************************
4 * Copyright (C) 1999, 2000, 2001 VideoLAN
5 * $Id: aout_ext-dec.c,v 1.2 2001/05/06 04:32:02 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 *****************************************************************************/
29 #include <stdio.h> /* "intf_msg.h" */
30 #include <stdlib.h> /* calloc(), malloc(), free() */
35 #include "mtime.h" /* mtime_t, mdate(), msleep() */
37 #include "intf_msg.h" /* intf_DbgMsg(), intf_ErrMsg() */
39 #include "audio_output.h"
40 #include "aout_common.h"
44 /*****************************************************************************
46 *****************************************************************************/
47 aout_fifo_t * aout_CreateFifo( int i_type, int i_channels, long l_rate,
48 long l_units, long l_frame_size,
51 aout_thread_t *p_aout;
54 /* Spawn an audio output if there is none */
55 vlc_mutex_lock( &p_aout_bank->lock );
57 if( p_aout_bank->i_count == 0 )
59 intf_Msg( "aout: no aout present, spawning one" );
61 p_aout = aout_CreateThread( NULL );
63 /* Everything failed */
66 vlc_mutex_unlock( &p_aout_bank->lock );
70 p_aout_bank->pp_aout[ p_aout_bank->i_count ] = p_aout;
71 p_aout_bank->i_count++;
75 /* Take the first audio output FIXME: take the best one */
76 p_aout = p_aout_bank->pp_aout[ 0 ];
79 /* Take the fifos lock */
80 vlc_mutex_lock( &p_aout->fifos_lock );
82 /* Looking for a free fifo structure */
83 for( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
85 if( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO )
87 /* Not very clever, but at least we know which fifo it is */
88 p_aout->fifo[i_fifo].i_fifo = i_fifo;
93 if( i_fifo == AOUT_MAX_FIFOS )
95 intf_ErrMsg( "aout error: no fifo available" );
96 vlc_mutex_unlock( &p_aout->fifos_lock );
97 vlc_mutex_unlock( &p_aout_bank->lock );
101 /* Initialize the new fifo structure */
102 switch ( p_aout->fifo[i_fifo].i_type = i_type )
104 case AOUT_INTF_MONO_FIFO:
105 case AOUT_INTF_STEREO_FIFO:
106 p_aout->fifo[i_fifo].b_die = 0;
108 p_aout->fifo[i_fifo].i_channels = i_channels;
109 p_aout->fifo[i_fifo].b_stereo = ( i_channels == 2 );
110 p_aout->fifo[i_fifo].l_rate = l_rate;
112 p_aout->fifo[i_fifo].buffer = p_buffer;
114 p_aout->fifo[i_fifo].l_unit = 0;
115 InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment,
116 l_rate, p_aout->l_rate );
117 p_aout->fifo[i_fifo].l_units = l_units;
120 case AOUT_ADEC_MONO_FIFO:
121 case AOUT_ADEC_STEREO_FIFO:
122 p_aout->fifo[i_fifo].b_die = 0;
124 p_aout->fifo[i_fifo].i_channels = i_channels;
125 p_aout->fifo[i_fifo].b_stereo = ( i_channels == 2 );
126 p_aout->fifo[i_fifo].l_rate = l_rate;
128 p_aout->fifo[i_fifo].l_frame_size = l_frame_size;
129 /* Allocate the memory needed to store the audio frames. As the
130 * fifo is a rotative fifo, we must be able to find out whether
131 * the fifo is full or empty, that's why we must in fact allocate
132 * memory for (AOUT_FIFO_SIZE+1) audio frames. */
133 p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16) *
134 ( AOUT_FIFO_SIZE + 1 ) * l_frame_size );
135 if ( p_aout->fifo[i_fifo].buffer == NULL )
137 intf_ErrMsg( "aout error: cannot create frame buffer" );
138 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
139 vlc_mutex_unlock( &p_aout->fifos_lock );
140 vlc_mutex_unlock( &p_aout_bank->lock );
144 /* Allocate the memory needed to store the dates of the frames */
145 p_aout->fifo[i_fifo].date =
146 malloc( sizeof(mtime_t) * ( AOUT_FIFO_SIZE + 1) );
148 if ( p_aout->fifo[i_fifo].date == NULL )
150 intf_ErrMsg( "aout error: cannot create date buffer");
151 free( p_aout->fifo[i_fifo].buffer );
152 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
153 vlc_mutex_unlock( &p_aout->fifos_lock );
154 vlc_mutex_unlock( &p_aout_bank->lock );
158 /* Set the fifo's buffer as empty (the first frame that is to be
159 * played is also the first frame that is not to be played) */
160 p_aout->fifo[i_fifo].l_start_frame = 0;
161 /* p_aout->fifo[i_fifo].l_next_frame = 0; */
162 p_aout->fifo[i_fifo].l_end_frame = 0;
164 /* Waiting for the audio decoder to compute enough frames to work
165 * out the fifo's current rate (as soon as the decoder has decoded
166 * enough frames, the members of the fifo structure that are not
167 * initialized now will be calculated) */
168 p_aout->fifo[i_fifo].b_start_frame = 0;
169 p_aout->fifo[i_fifo].b_next_frame = 0;
173 intf_ErrMsg( "aout error: unknown fifo type 0x%x",
174 p_aout->fifo[i_fifo].i_type );
175 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
176 vlc_mutex_unlock( &p_aout->fifos_lock );
177 vlc_mutex_unlock( &p_aout_bank->lock );
181 /* Release the fifos lock */
182 vlc_mutex_unlock( &p_aout->fifos_lock );
183 vlc_mutex_unlock( &p_aout_bank->lock );
185 intf_WarnMsg( 2, "aout info: fifo #%i allocated, %i channels, rate %li",
186 p_aout->fifo[i_fifo].i_fifo, p_aout->fifo[i_fifo].i_channels,
187 p_aout->fifo[i_fifo].l_rate );
189 /* Return the pointer to the fifo structure */
190 return( &p_aout->fifo[i_fifo] );
193 /*****************************************************************************
195 *****************************************************************************/
196 void aout_DestroyFifo( aout_fifo_t * p_fifo )
198 intf_WarnMsg( 2, "aout info: fifo #%i destroyed", p_fifo->i_fifo );
203 /*****************************************************************************
205 *****************************************************************************/
206 void aout_FreeFifo( aout_fifo_t * p_fifo )
208 switch ( p_fifo->i_type )
210 case AOUT_EMPTY_FIFO:
214 case AOUT_INTF_MONO_FIFO:
215 case AOUT_INTF_STEREO_FIFO:
217 free( p_fifo->buffer );
218 p_fifo->i_type = AOUT_EMPTY_FIFO;
222 case AOUT_ADEC_MONO_FIFO:
223 case AOUT_ADEC_STEREO_FIFO:
225 free( p_fifo->buffer );
226 free( p_fifo->date );
227 p_fifo->i_type = AOUT_EMPTY_FIFO;