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"
40 /*****************************************************************************
41 * aout_DecNew : create a decoder
42 *****************************************************************************/
43 static aout_input_t
* DecNew( aout_instance_t
* p_aout
,
44 audio_sample_format_t
*p_format
,
45 const audio_replay_gain_t
*p_replay_gain
,
46 const aout_request_vout_t
*p_request_vout
)
48 aout_input_t
* p_input
;
50 /* Sanitize audio format */
51 if( p_format
->i_channels
> 32 )
53 msg_Err( p_aout
, "too many audio channels (%u)",
54 p_format
->i_channels
);
57 if( p_format
->i_channels
<= 0 )
59 msg_Err( p_aout
, "no audio channels" );
62 if( p_format
->i_channels
!= aout_FormatNbChannels( p_format
) )
64 msg_Err( p_aout
, "incompatible audio channels count with layout mask" );
68 if( p_format
->i_rate
> 192000 )
70 msg_Err( p_aout
, "excessive audio sample frequency (%u)",
74 if( p_format
->i_rate
< 4000 )
76 msg_Err( p_aout
, "too low audio sample frequency (%u)",
81 /* We can only be called by the decoder, so no need to lock
83 aout_lock_mixer( p_aout
);
85 if ( p_aout
->i_nb_inputs
>= AOUT_MAX_INPUTS
)
87 msg_Err( p_aout
, "too many inputs already (%d)", p_aout
->i_nb_inputs
);
91 p_input
= calloc( 1, sizeof(aout_input_t
));
95 vlc_mutex_init( &p_input
->lock
);
97 p_input
->b_changed
= false;
98 p_input
->b_error
= true;
99 p_input
->b_paused
= false;
100 p_input
->i_pause_date
= 0;
102 aout_FormatPrepare( p_format
);
104 memcpy( &p_input
->input
, p_format
,
105 sizeof(audio_sample_format_t
) );
107 p_input
->replay_gain
= *p_replay_gain
;
109 aout_lock_input_fifos( p_aout
);
110 p_aout
->pp_inputs
[p_aout
->i_nb_inputs
] = p_input
;
111 p_aout
->i_nb_inputs
++;
113 if ( !p_aout
->p_mixer
)
117 var_Destroy( p_aout
, "audio-device" );
118 var_Destroy( p_aout
, "audio-channels" );
120 /* Recreate the output using the new format. */
121 if ( aout_OutputNew( p_aout
, p_format
) < 0 )
123 for ( i
= 0; i
< p_aout
->i_nb_inputs
- 1; i
++ )
125 aout_lock_input( p_aout
, p_aout
->pp_inputs
[i
] );
126 aout_InputDelete( p_aout
, p_aout
->pp_inputs
[i
] );
127 aout_unlock_input( p_aout
, p_aout
->pp_inputs
[i
] );
129 aout_unlock_input_fifos( p_aout
);
130 aout_unlock_mixer( p_aout
);
134 /* Create other input streams. */
135 for ( i
= 0; i
< p_aout
->i_nb_inputs
- 1; i
++ )
137 aout_input_t
*p_input
= p_aout
->pp_inputs
[i
];
139 aout_lock_input( p_aout
, p_input
);
140 aout_InputDelete( p_aout
, p_input
);
141 aout_InputNew( p_aout
, p_input
, &p_input
->request_vout
);
142 aout_unlock_input( p_aout
, p_input
);
147 aout_MixerDelete( p_aout
);
150 if ( aout_MixerNew( p_aout
) == -1 )
152 aout_OutputDelete( p_aout
);
153 aout_unlock_input_fifos( p_aout
);
157 aout_InputNew( p_aout
, p_input
, p_request_vout
);
158 aout_unlock_input_fifos( p_aout
);
160 aout_unlock_mixer( p_aout
);
165 aout_unlock_mixer( p_aout
);
169 aout_input_t
* __aout_DecNew( vlc_object_t
* p_this
,
170 aout_instance_t
** pp_aout
,
171 audio_sample_format_t
* p_format
,
172 const audio_replay_gain_t
*p_replay_gain
,
173 const aout_request_vout_t
*p_request_video
)
175 aout_instance_t
*p_aout
= *pp_aout
;
176 if ( p_aout
== NULL
)
178 msg_Dbg( p_this
, "no aout present, spawning one" );
179 p_aout
= aout_New( p_this
);
181 /* Everything failed, I'm a loser, I just wanna die */
185 vlc_object_attach( p_aout
, p_this
);
189 return DecNew( p_aout
, p_format
, p_replay_gain
, p_request_video
);
192 /*****************************************************************************
193 * aout_DecDelete : delete a decoder
194 *****************************************************************************/
195 int aout_DecDelete( aout_instance_t
* p_aout
, aout_input_t
* p_input
)
199 /* This function can only be called by the decoder itself, so no need
200 * to lock p_input->lock. */
201 aout_lock_mixer( p_aout
);
203 for ( i_input
= 0; i_input
< p_aout
->i_nb_inputs
; i_input
++ )
205 if ( p_aout
->pp_inputs
[i_input
] == p_input
)
211 if ( i_input
== p_aout
->i_nb_inputs
)
213 msg_Err( p_aout
, "cannot find an input to delete" );
214 aout_unlock_mixer( p_aout
);
218 /* Remove the input from the list. */
219 memmove( &p_aout
->pp_inputs
[i_input
], &p_aout
->pp_inputs
[i_input
+ 1],
220 (AOUT_MAX_INPUTS
- i_input
- 1) * sizeof(aout_input_t
*) );
221 p_aout
->i_nb_inputs
--;
223 aout_InputDelete( p_aout
, p_input
);
225 vlc_mutex_destroy( &p_input
->lock
);
228 if ( !p_aout
->i_nb_inputs
)
230 aout_OutputDelete( p_aout
);
231 aout_MixerDelete( p_aout
);
232 var_Destroy( p_aout
, "audio-device" );
233 var_Destroy( p_aout
, "audio-channels" );
236 aout_unlock_mixer( p_aout
);
246 /*****************************************************************************
247 * aout_DecNewBuffer : ask for a new empty buffer
248 *****************************************************************************/
249 aout_buffer_t
* aout_DecNewBuffer( aout_input_t
* p_input
,
250 size_t i_nb_samples
)
252 aout_buffer_t
* p_buffer
;
255 aout_lock_input( NULL
, p_input
);
257 if ( p_input
->b_error
)
259 aout_unlock_input( NULL
, p_input
);
263 duration
= (1000000 * (mtime_t
)i_nb_samples
) / p_input
->input
.i_rate
;
265 /* This necessarily allocates in the heap. */
266 p_buffer
= aout_BufferAlloc( &p_input
->input_alloc
, duration
, NULL
);
267 if( p_buffer
!= NULL
)
268 p_buffer
->i_buffer
= i_nb_samples
* p_input
->input
.i_bytes_per_frame
269 / p_input
->input
.i_frame_length
;
271 /* Suppose the decoder doesn't have more than one buffered buffer */
272 p_input
->b_changed
= false;
274 aout_unlock_input( NULL
, p_input
);
276 if( p_buffer
== NULL
)
279 p_buffer
->i_nb_samples
= i_nb_samples
;
280 p_buffer
->i_pts
= p_buffer
->i_length
= 0;
284 /*****************************************************************************
285 * aout_DecDeleteBuffer : destroy an undecoded buffer
286 *****************************************************************************/
287 void aout_DecDeleteBuffer( aout_instance_t
* p_aout
, aout_input_t
* p_input
,
288 aout_buffer_t
* p_buffer
)
290 (void)p_aout
; (void)p_input
;
291 aout_BufferFree( p_buffer
);
294 /*****************************************************************************
295 * aout_DecPlay : filter & mix the decoded buffer
296 *****************************************************************************/
297 int aout_DecPlay( aout_instance_t
* p_aout
, aout_input_t
* p_input
,
298 aout_buffer_t
* p_buffer
, int i_input_rate
)
300 assert( i_input_rate
>= INPUT_RATE_DEFAULT
/ AOUT_MAX_INPUT_RATE
&&
301 i_input_rate
<= INPUT_RATE_DEFAULT
* AOUT_MAX_INPUT_RATE
);
303 assert( p_buffer
->i_pts
> 0 );
305 p_buffer
->i_length
= (mtime_t
)p_buffer
->i_nb_samples
* 1000000
306 / p_input
->input
.i_rate
;
308 aout_lock_mixer( p_aout
);
309 aout_lock_input( p_aout
, p_input
);
311 if( p_input
->b_error
)
313 aout_unlock_input( p_aout
, p_input
);
314 aout_unlock_mixer( p_aout
);
316 aout_BufferFree( p_buffer
);
320 if( p_input
->b_changed
)
322 /* Maybe the allocation size has changed. Re-allocate a buffer. */
323 aout_buffer_t
* p_new_buffer
;
324 mtime_t duration
= (1000000 * (mtime_t
)p_buffer
->i_nb_samples
)
325 / p_input
->input
.i_rate
;
327 p_new_buffer
= aout_BufferAlloc( &p_input
->input_alloc
, duration
, NULL
);
328 vlc_memcpy( p_new_buffer
->p_buffer
, p_buffer
->p_buffer
,
329 p_buffer
->i_buffer
);
330 p_new_buffer
->i_nb_samples
= p_buffer
->i_nb_samples
;
331 p_new_buffer
->i_buffer
= p_buffer
->i_buffer
;
332 p_new_buffer
->i_pts
= p_buffer
->i_pts
;
333 p_new_buffer
->i_length
= p_buffer
->i_length
;
334 aout_BufferFree( p_buffer
);
335 p_buffer
= p_new_buffer
;
336 p_input
->b_changed
= false;
339 aout_InputCheckAndRestart( p_aout
, p_input
);
340 aout_unlock_mixer( p_aout
);
342 int i_ret
= aout_InputPlay( p_aout
, p_input
, p_buffer
, i_input_rate
);
344 aout_unlock_input( p_aout
, p_input
);
349 /* Run the mixer if it is able to run. */
350 aout_lock_mixer( p_aout
);
352 aout_MixerRun( p_aout
);
354 aout_unlock_mixer( p_aout
);
359 int aout_DecGetResetLost( aout_instance_t
*p_aout
, aout_input_t
*p_input
)
361 aout_lock_input( p_aout
, p_input
);
362 int i_value
= p_input
->i_buffer_lost
;
363 p_input
->i_buffer_lost
= 0;
364 aout_unlock_input( p_aout
, p_input
);
369 void aout_DecChangePause( aout_instance_t
*p_aout
, aout_input_t
*p_input
, bool b_paused
, mtime_t i_date
)
371 mtime_t i_duration
= 0;
372 aout_lock_input( p_aout
, p_input
);
373 assert( !p_input
->b_paused
|| !b_paused
);
374 if( p_input
->b_paused
)
376 i_duration
= i_date
- p_input
->i_pause_date
;
378 p_input
->b_paused
= b_paused
;
379 p_input
->i_pause_date
= i_date
;
380 aout_unlock_input( p_aout
, p_input
);
382 if( i_duration
!= 0 )
384 aout_lock_mixer( p_aout
);
385 for( aout_buffer_t
*p
= p_input
->mixer
.fifo
.p_first
; p
!= NULL
; p
= p
->p_next
)
387 p
->i_pts
+= i_duration
;
389 aout_unlock_mixer( p_aout
);
393 void aout_DecFlush( aout_instance_t
*p_aout
, aout_input_t
*p_input
)
395 aout_lock_input_fifos( p_aout
);
397 aout_FifoSet( p_aout
, &p_input
->mixer
.fifo
, 0 );
398 p_input
->mixer
.begin
= NULL
;
400 aout_unlock_input_fifos( p_aout
);