1 /*****************************************************************************
2 * dec.c : audio output API towards decoders
3 *****************************************************************************
4 * Copyright (C) 2002-2007 the VideoLAN team
7 * Authors: Christophe Massiot <massiot@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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
33 #include <vlc_common.h>
36 #include <vlc_input.h>
38 #include "aout_internal.h"
42 * Creates an audio output
44 aout_input_t *aout_DecNew( audio_output_t *p_aout,
45 audio_sample_format_t *p_format,
46 const audio_replay_gain_t *p_replay_gain,
47 const aout_request_vout_t *p_request_vout )
49 /* Sanitize audio format */
50 if( p_format->i_channels > 32 )
52 msg_Err( p_aout, "too many audio channels (%u)",
53 p_format->i_channels );
56 if( p_format->i_channels <= 0 )
58 msg_Err( p_aout, "no audio channels" );
61 if( p_format->i_channels != aout_FormatNbChannels( p_format ) )
63 msg_Err( p_aout, "incompatible audio channels count with layout mask" );
67 if( p_format->i_rate > 192000 )
69 msg_Err( p_aout, "excessive audio sample frequency (%u)",
73 if( p_format->i_rate < 4000 )
75 msg_Err( p_aout, "too low audio sample frequency (%u)",
80 aout_input_t *p_input = calloc( 1, sizeof(aout_input_t));
84 p_input->b_error = true;
85 p_input->b_paused = false;
86 p_input->i_pause_date = 0;
88 aout_FormatPrepare( p_format );
90 memcpy( &p_input->input, p_format,
91 sizeof(audio_sample_format_t) );
93 p_input->replay_gain = *p_replay_gain;
95 /* We can only be called by the decoder, so no need to lock
98 assert( p_aout->p_input == NULL );
99 p_aout->p_input = p_input;
101 var_Destroy( p_aout, "audio-device" );
102 var_Destroy( p_aout, "audio-channels" );
104 /* Recreate the output using the new format. */
105 if( aout_OutputNew( p_aout, p_format ) < 0 )
106 #warning Input without output and mixer = bad idea.
109 assert( p_aout->mixer == NULL );
110 p_aout->mixer = aout_MixerNew( p_aout, &p_aout->mixer_format );
111 if( p_aout->mixer == NULL )
113 aout_OutputDelete( p_aout );
114 #warning Memory leak.
119 aout_InputNew( p_aout, p_input, p_request_vout );
121 aout_unlock( p_aout );
125 /*****************************************************************************
126 * aout_DecDelete : delete a decoder
127 *****************************************************************************/
128 void aout_DecDelete( audio_output_t * p_aout, aout_input_t * p_input )
131 /* Remove the input. */
132 assert( p_input == p_aout->p_input ); /* buggy decoder? */
133 p_aout->p_input = NULL;
134 aout_InputDelete( p_aout, p_input );
136 aout_OutputDelete( p_aout );
137 aout_MixerDelete( p_aout->mixer );
138 p_aout->mixer = NULL;
139 var_Destroy( p_aout, "audio-device" );
140 var_Destroy( p_aout, "audio-channels" );
142 aout_unlock( p_aout );
151 /*****************************************************************************
152 * aout_DecNewBuffer : ask for a new empty buffer
153 *****************************************************************************/
154 aout_buffer_t * aout_DecNewBuffer( aout_input_t * p_input,
155 size_t i_nb_samples )
157 size_t length = i_nb_samples * p_input->input.i_bytes_per_frame
158 / p_input->input.i_frame_length;
159 block_t *block = block_Alloc( length );
160 if( likely(block != NULL) )
162 block->i_nb_samples = i_nb_samples;
163 block->i_pts = block->i_length = 0;
168 /*****************************************************************************
169 * aout_DecDeleteBuffer : destroy an undecoded buffer
170 *****************************************************************************/
171 void aout_DecDeleteBuffer( audio_output_t * p_aout, aout_input_t * p_input,
172 aout_buffer_t * p_buffer )
174 (void)p_aout; (void)p_input;
175 aout_BufferFree( p_buffer );
178 /*****************************************************************************
179 * aout_DecPlay : filter & mix the decoded buffer
180 *****************************************************************************/
181 int aout_DecPlay( audio_output_t * p_aout, aout_input_t * p_input,
182 aout_buffer_t * p_buffer, int i_input_rate )
184 assert( i_input_rate >= INPUT_RATE_DEFAULT / AOUT_MAX_INPUT_RATE &&
185 i_input_rate <= INPUT_RATE_DEFAULT * AOUT_MAX_INPUT_RATE );
186 assert( p_buffer->i_pts > 0 );
188 p_buffer->i_length = (mtime_t)p_buffer->i_nb_samples * 1000000
189 / p_input->input.i_rate;
192 if( p_input->b_error )
194 aout_unlock( p_aout );
195 aout_BufferFree( p_buffer );
199 aout_InputCheckAndRestart( p_aout, p_input );
200 aout_InputPlay( p_aout, p_input, p_buffer, i_input_rate );
202 const float amp = p_aout->mixer_multiplier * p_input->multiplier;
203 while( (p_buffer = aout_OutputSlice( p_aout, &p_input->fifo ) ) != NULL )
205 aout_MixerRun( p_aout->mixer, p_buffer, amp );
206 aout_OutputPlay( p_aout, p_buffer );
208 aout_unlock( p_aout );
212 int aout_DecGetResetLost( audio_output_t *p_aout, aout_input_t *p_input )
217 val = p_input->i_buffer_lost;
218 p_input->i_buffer_lost = 0;
219 aout_unlock( p_aout );
224 void aout_DecChangePause( audio_output_t *p_aout, aout_input_t *p_input, bool b_paused, mtime_t i_date )
226 mtime_t i_duration = 0;
229 assert( p_aout->p_input == p_input );
230 assert( !p_input->b_paused || !b_paused );
231 if( p_input->b_paused )
233 i_duration = i_date - p_input->i_pause_date;
235 p_input->b_paused = b_paused;
236 p_input->i_pause_date = i_date;
238 if( i_duration != 0 )
240 aout_FifoMoveDates( &p_input->fifo, i_duration );
241 aout_FifoMoveDates( &p_aout->fifo, i_duration );
243 aout_OutputPause( p_aout, b_paused, i_date );
244 aout_unlock( p_aout );
247 void aout_DecFlush( audio_output_t *p_aout, aout_input_t *p_input )
250 aout_FifoReset( &p_input->fifo );
251 aout_FifoReset( &p_aout->fifo );
252 aout_OutputFlush( p_aout, false );
253 aout_unlock( p_aout );
256 bool aout_DecIsEmpty( audio_output_t * p_aout, aout_input_t * p_input )
261 end_date = aout_FifoNextStart( &p_input->fifo );
262 aout_unlock( p_aout );
263 return end_date == VLC_TS_INVALID || end_date <= mdate();