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 int aout_DecNew( audio_output_t *p_aout,
45 const 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;
87 p_input->replay_gain = *p_replay_gain;
89 /* We can only be called by the decoder, so no need to lock
91 aout_owner_t *owner = aout_owner(p_aout);
93 assert (owner->input == NULL);
95 var_Destroy( p_aout, "audio-device" );
96 var_Destroy( p_aout, "audio-channels" );
98 /* Recreate the output using the new format. */
99 owner->input_format = *p_format;
100 if( aout_OutputNew( p_aout, p_format ) < 0 )
103 assert (owner->volume.mixer == NULL);
104 owner->volume.mixer = aout_MixerNew (p_aout, owner->mixer_format.i_format);
106 date_Init (&owner->sync.date, owner->mixer_format.i_rate, 1);
107 date_Set (&owner->sync.date, VLC_TS_INVALID);
109 owner->input = p_input;
110 aout_InputNew( p_aout, p_format, &owner->mixer_format, p_input,
112 aout_unlock( p_aout );
115 aout_unlock( p_aout );
120 /*****************************************************************************
121 * aout_DecDelete : delete a decoder
122 *****************************************************************************/
123 void aout_DecDelete( audio_output_t * p_aout )
125 aout_owner_t *owner = aout_owner (p_aout);
127 struct audio_mixer *mixer;
130 /* Remove the input. */
131 input = owner->input;
132 aout_InputDelete (p_aout, input);
135 aout_OutputDelete( p_aout );
136 mixer = owner->volume.mixer;
137 owner->volume.mixer = NULL;
138 var_Destroy( p_aout, "audio-device" );
139 var_Destroy( p_aout, "audio-channels" );
141 aout_unlock( p_aout );
143 aout_MixerDelete (mixer);
147 static void aout_CheckRestart (audio_output_t *aout)
149 aout_owner_t *owner = aout_owner (aout);
150 aout_input_t *input = owner->input;
152 aout_assert_locked (aout);
154 if (likely(!owner->need_restart))
156 owner->need_restart = false;
158 /* Reinitializes the output */
159 aout_InputDelete (aout, owner->input);
160 aout_MixerDelete (owner->volume.mixer);
161 owner->volume.mixer = NULL;
162 aout_OutputDelete (aout);
164 if (aout_OutputNew (aout, &owner->input_format))
166 input->b_error = true;
167 return; /* we are officially screwed */
170 owner->volume.mixer = aout_MixerNew (aout, owner->mixer_format.i_format);
172 if (aout_InputNew (aout, &owner->input_format, &owner->mixer_format, input,
173 &input->request_vout))
174 assert (input->b_error);
176 assert (!input->b_error);
180 * Restarts the audio filter chain if needed.
182 static void aout_InputCheckAndRestart (audio_output_t *aout)
184 aout_owner_t *owner = aout_owner (aout);
185 aout_input_t *input = owner->input;
187 aout_assert_locked (aout);
189 if (!input->b_restart)
191 input->b_restart = false;
193 aout_InputDelete (aout, input);
194 aout_InputNew (aout, &owner->input_format, &owner->mixer_format,
195 input, &input->request_vout);
199 * This function will safely mark aout input to be restarted as soon as
200 * possible to take configuration changes into account
202 void aout_InputRequestRestart (audio_output_t *aout)
205 if (aout_owner (aout)->input != NULL)
206 aout_owner (aout)->input->b_restart = true;
215 /*****************************************************************************
216 * aout_DecNewBuffer : ask for a new empty buffer
217 *****************************************************************************/
218 block_t *aout_DecNewBuffer (audio_output_t *aout, size_t samples)
220 /* NOTE: the caller is responsible for serializing input change */
221 aout_owner_t *owner = aout_owner (aout);
223 size_t length = samples * owner->input_format.i_bytes_per_frame
224 / owner->input_format.i_frame_length;
225 block_t *block = block_Alloc( length );
226 if( likely(block != NULL) )
228 block->i_nb_samples = samples;
229 block->i_pts = block->i_length = 0;
234 /*****************************************************************************
235 * aout_DecDeleteBuffer : destroy an undecoded buffer
236 *****************************************************************************/
237 void aout_DecDeleteBuffer (audio_output_t *aout, block_t *block)
240 aout_BufferFree (block);
243 /*****************************************************************************
244 * aout_DecPlay : filter & mix the decoded buffer
245 *****************************************************************************/
246 int aout_DecPlay (audio_output_t *p_aout, block_t *p_buffer, int i_input_rate)
248 aout_owner_t *owner = aout_owner (p_aout);
249 aout_input_t *p_input = owner->input;
251 assert( i_input_rate >= INPUT_RATE_DEFAULT / AOUT_MAX_INPUT_RATE &&
252 i_input_rate <= INPUT_RATE_DEFAULT * AOUT_MAX_INPUT_RATE );
253 assert( p_buffer->i_pts > 0 );
255 p_buffer->i_length = (mtime_t)p_buffer->i_nb_samples * 1000000
256 / owner->input_format.i_rate;
259 if( p_input->b_error )
261 aout_unlock( p_aout );
262 aout_BufferFree( p_buffer );
266 aout_CheckRestart( p_aout );
267 aout_InputCheckAndRestart (p_aout);
270 p_buffer = aout_InputPlay (p_aout, p_input, p_buffer, i_input_rate,
272 if( p_buffer != NULL )
274 date_Increment (&owner->sync.date, p_buffer->i_nb_samples);
277 float amp = owner->volume.multiplier * p_input->multiplier;
278 aout_MixerRun (owner->volume.mixer, p_buffer, amp);
281 aout_OutputPlay( p_aout, p_buffer );
284 aout_unlock( p_aout );
288 int aout_DecGetResetLost (audio_output_t *aout)
290 aout_owner_t *owner = aout_owner (aout);
291 aout_input_t *input = owner->input;
295 val = input->i_buffer_lost;
296 input->i_buffer_lost = 0;
302 void aout_DecChangePause (audio_output_t *aout, bool paused, mtime_t date)
304 aout_owner_t *owner = aout_owner (aout);
307 /* XXX: Should the date be offset by the pause duration instead? */
308 date_Set (&owner->sync.date, VLC_TS_INVALID);
309 aout_OutputPause (aout, paused, date);
313 void aout_DecFlush (audio_output_t *aout)
315 aout_owner_t *owner = aout_owner (aout);
318 date_Set (&owner->sync.date, VLC_TS_INVALID);
319 aout_OutputFlush (aout, false);
323 bool aout_DecIsEmpty (audio_output_t *aout)
325 aout_owner_t *owner = aout_owner (aout);
329 /* FIXME: tell output to drain */
330 end_date = date_Get (&owner->sync.date);
332 return end_date == VLC_TS_INVALID || end_date <= mdate();
336 * Notifies the audio input of the drift from the requested audio
337 * playback timestamp (@ref block_t.i_pts) to the anticipated playback time
338 * as reported by the audio output hardware.
339 * Depending on the drift amplitude, the input core may ignore the drift
340 * trigger upsampling or downsampling, or even discard samples.
341 * Future VLC versions may instead adjust the input decoding speed.
343 * The audio output plugin is responsible for estimating the ideal current
344 * playback time defined as follows:
345 * ideal time = buffer timestamp - (output latency + pending buffer duration)
347 * Practically, this is the PTS (block_t.i_pts) of the current buffer minus
348 * the latency reported by the output programming interface.
349 * Computing the estimated drift directly would probably be more intuitive.
350 * However the use of an absolute time value does not introduce extra
351 * measurement errors due to the CPU scheduling jitter and clock resolution.
352 * Furthermore, the ideal while it is an abstract value, is easy for most
353 * audio output plugins to compute.
354 * The following definition is equivalent but depends on the clock time:
355 * ideal time = real time + drift
357 * @note If aout_LatencyReport() is never called, the core will assume that
360 * @param ideal estimated ideal time as defined above.
362 void aout_TimeReport (audio_output_t *aout, mtime_t ideal)
364 mtime_t delta = mdate() - ideal /* = -drift */;
366 aout_assert_locked (aout);
367 if (delta < -AOUT_MAX_PTS_ADVANCE || +AOUT_MAX_PTS_DELAY < delta)
369 aout_owner_t *owner = aout_owner (aout);
371 msg_Warn (aout, "not synchronized (%"PRId64" us), resampling",
373 if (date_Get (&owner->sync.date) != VLC_TS_INVALID)
374 date_Move (&owner->sync.date, delta);