]> git.sesse.net Git - vlc/blob - src/audio_output/input.c
62e218e0c43c5891ec88f201ef9a443b224f049e
[vlc] / src / audio_output / input.c
1 /*****************************************************************************
2  * input.c : internal management of input streams for the audio output
3  *****************************************************************************
4  * Copyright (C) 2002 VideoLAN
5  * $Id: input.c,v 1.32 2003/02/21 22:59:38 gbazin Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                            /* calloc(), malloc(), free() */
28 #include <string.h>
29
30 #include <vlc/vlc.h>
31
32 #ifdef HAVE_ALLOCA_H
33 #   include <alloca.h>
34 #endif
35
36 #include "audio_output.h"
37 #include "aout_internal.h"
38
39 /*****************************************************************************
40  * aout_InputNew : allocate a new input and rework the filter pipeline
41  *****************************************************************************/
42 int aout_InputNew( aout_instance_t * p_aout, aout_input_t * p_input )
43 {
44     audio_sample_format_t intermediate_format, headphone_intermediate_format;
45     aout_filter_t * p_headphone_filter;
46     vlc_bool_t b_use_headphone_filter = VLC_FALSE;
47
48     aout_FormatPrint( p_aout, "input", &p_input->input );
49
50     /* Prepare FIFO. */
51     aout_FifoInit( p_aout, &p_input->fifo, p_aout->mixer.mixer.i_rate );
52     p_input->p_first_byte_to_mix = NULL;
53
54     /* Prepare format structure */
55     memcpy( &intermediate_format, &p_aout->mixer.mixer,
56             sizeof(audio_sample_format_t) );
57     intermediate_format.i_rate = p_input->input.i_rate;
58
59     /* Headphone filter add-ons. */
60     memcpy( &headphone_intermediate_format, &p_aout->mixer.mixer,
61             sizeof(audio_sample_format_t) );
62     headphone_intermediate_format.i_rate = p_input->input.i_rate;
63     if ( config_GetInt( p_aout , "headphone" ) )
64     {
65         /* Do we use heaphone filter ? */
66         if ( intermediate_format.i_physical_channels
67                 == ( AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT )
68             && ( intermediate_format.i_format != VLC_FOURCC('f','l','3','2')
69                 || intermediate_format.i_format != VLC_FOURCC('f','i','3','2')
70                 ) )
71         {
72             b_use_headphone_filter = VLC_TRUE;
73         }
74     }
75     if ( b_use_headphone_filter == VLC_TRUE )
76     {
77         /* Split the filter pipeline. */
78         headphone_intermediate_format.i_physical_channels = p_input->input.i_physical_channels;
79         headphone_intermediate_format.i_original_channels = p_input->input.i_original_channels;
80         headphone_intermediate_format.i_bytes_per_frame =
81                 headphone_intermediate_format.i_bytes_per_frame
82                 * aout_FormatNbChannels( &headphone_intermediate_format )
83                 / aout_FormatNbChannels( &intermediate_format );
84     }
85
86     /* Create filters. */
87     if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
88                                      &p_input->i_nb_filters, &p_input->input,
89                                      &headphone_intermediate_format ) < 0 )
90     {
91         msg_Err( p_aout, "couldn't set an input pipeline" );
92
93         aout_FifoDestroy( p_aout, &p_input->fifo );
94         p_input->b_error = 1;
95
96         return -1;
97     }
98
99     /* Headphone filter add-ons. */
100     if ( b_use_headphone_filter == VLC_TRUE )
101     {
102         /* create a vlc object */
103         p_headphone_filter = vlc_object_create( p_aout
104                 , sizeof(aout_filter_t) );
105         if ( p_headphone_filter == NULL )
106         {
107             msg_Err( p_aout, "couldn't open the headphone virtual spatialization module" );
108             aout_FifoDestroy( p_aout, &p_input->fifo );
109             p_input->b_error = 1;
110             return -1;
111         }
112         vlc_object_attach( p_headphone_filter, p_aout );
113
114         /* find the headphone filter */
115         memcpy( &p_headphone_filter->input, &headphone_intermediate_format
116                 , sizeof(audio_sample_format_t) );
117         memcpy( &p_headphone_filter->output, &intermediate_format
118                 , sizeof(audio_sample_format_t) );
119         p_headphone_filter->p_module = module_Need( p_headphone_filter, "audio filter"
120                 , "headphone" );
121         if ( p_headphone_filter->p_module == NULL )
122         {
123             vlc_object_detach( p_headphone_filter );
124             vlc_object_destroy( p_headphone_filter );
125
126             msg_Err( p_aout, "couldn't open the headphone virtual spatialization module" );
127             aout_FifoDestroy( p_aout, &p_input->fifo );
128             p_input->b_error = 1;
129             return -1;
130         }
131
132         /* success */
133         p_headphone_filter->b_reinit = VLC_TRUE;
134         p_input->pp_filters[p_input->i_nb_filters++] = p_headphone_filter;
135     }
136
137     /* Prepare hints for the buffer allocator. */
138     p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
139     p_input->input_alloc.i_bytes_per_sec = -1;
140
141     if ( AOUT_FMT_NON_LINEAR( &p_aout->mixer.mixer ) )
142     {
143         p_input->i_nb_resamplers = 0;
144     }
145     else
146     {
147         /* Create resamplers. */
148         intermediate_format.i_rate = (__MAX(p_input->input.i_rate,
149                                             p_aout->mixer.mixer.i_rate)
150                                  * (100 + AOUT_MAX_RESAMPLING)) / 100;
151         if ( intermediate_format.i_rate == p_aout->mixer.mixer.i_rate )
152         {
153             /* Just in case... */
154             intermediate_format.i_rate++;
155         }
156         if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_resamplers,
157                                          &p_input->i_nb_resamplers,
158                                          &intermediate_format,
159                                          &p_aout->mixer.mixer ) < 0 )
160         {
161             msg_Err( p_aout, "couldn't set a resampler pipeline" );
162
163             aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters,
164                                          p_input->i_nb_filters );
165             aout_FifoDestroy( p_aout, &p_input->fifo );
166             p_input->b_error = 1;
167
168             return -1;
169         }
170
171         aout_FiltersHintBuffers( p_aout, p_input->pp_resamplers,
172                                  p_input->i_nb_resamplers,
173                                  &p_input->input_alloc );
174
175         /* Setup the initial rate of the resampler */
176         p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
177     }
178     p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
179
180     p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
181     aout_FiltersHintBuffers( p_aout, p_input->pp_filters,
182                              p_input->i_nb_filters,
183                              &p_input->input_alloc );
184
185     /* i_bytes_per_sec is still == -1 if no filters */
186     p_input->input_alloc.i_bytes_per_sec = __MAX(
187                                     p_input->input_alloc.i_bytes_per_sec,
188                                     (int)(p_input->input.i_bytes_per_frame
189                                      * p_input->input.i_rate
190                                      / p_input->input.i_frame_length) );
191     /* Allocate in the heap, it is more convenient for the decoder. */
192     p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
193
194     p_input->b_error = 0;
195
196     return 0;
197 }
198
199 /*****************************************************************************
200  * aout_InputDelete : delete an input
201  *****************************************************************************
202  * This function must be entered with the mixer lock.
203  *****************************************************************************/
204 int aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input )
205 {
206     if ( p_input->b_error ) return 0;
207
208     aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters,
209                                  p_input->i_nb_filters );
210     aout_FiltersDestroyPipeline( p_aout, p_input->pp_resamplers,
211                                  p_input->i_nb_resamplers );
212     aout_FifoDestroy( p_aout, &p_input->fifo );
213
214     return 0;
215 }
216
217 /*****************************************************************************
218  * aout_InputPlay : play a buffer
219  *****************************************************************************
220  * This function must be entered with the input lock.
221  *****************************************************************************/
222 int aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
223                     aout_buffer_t * p_buffer )
224 {
225     mtime_t start_date;
226
227     /* We don't care if someone changes the start date behind our back after
228      * this. We'll deal with that when pushing the buffer, and compensate
229      * with the next incoming buffer. */
230     vlc_mutex_lock( &p_aout->input_fifos_lock );
231     start_date = aout_FifoNextStart( p_aout, &p_input->fifo );
232     vlc_mutex_unlock( &p_aout->input_fifos_lock );
233
234     if ( start_date != 0 && start_date < mdate() )
235     {
236         /* The decoder is _very_ late. This can only happen if the user
237          * pauses the stream (or if the decoder is buggy, which cannot
238          * happen :). */
239         msg_Warn( p_aout, "computed PTS is out of range ("I64Fd"), "
240                   "clearing out", mdate() - start_date );
241         vlc_mutex_lock( &p_aout->input_fifos_lock );
242         aout_FifoSet( p_aout, &p_input->fifo, 0 );
243         p_input->p_first_byte_to_mix = NULL;
244         vlc_mutex_unlock( &p_aout->input_fifos_lock );
245         if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
246             msg_Warn( p_aout, "timing screwed, stopping resampling" );
247         p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
248         if ( p_input->i_nb_resamplers != 0 )
249         {
250             p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
251             p_input->pp_resamplers[0]->b_reinit = VLC_TRUE;
252         }
253         start_date = 0;
254     }
255
256     if ( p_buffer->start_date < mdate() + AOUT_MIN_PREPARE_TIME )
257     {
258         /* The decoder gives us f*cked up PTS. It's its business, but we
259          * can't present it anyway, so drop the buffer. */
260         msg_Warn( p_aout, "PTS is out of range ("I64Fd"), dropping buffer",
261                   mdate() - p_buffer->start_date );
262         aout_BufferFree( p_buffer );
263
264         return 0;
265     }
266
267     if ( start_date == 0 ) start_date = p_buffer->start_date;
268
269     /* Run pre-filters. */
270     aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters,
271                       &p_buffer );
272
273     /* Run the resampler if needed.
274      * We first need to calculate the output rate of this resampler. */
275     if ( ( p_input->i_resampling_type == AOUT_RESAMPLING_NONE ) &&
276          ( start_date < p_buffer->start_date - AOUT_PTS_TOLERANCE
277            || start_date > p_buffer->start_date + AOUT_PTS_TOLERANCE ) &&
278          p_input->i_nb_resamplers > 0 )
279     {
280         /* Can happen in several circumstances :
281          * 1. A problem at the input (clock drift)
282          * 2. A small pause triggered by the user
283          * 3. Some delay in the output stage, causing a loss of lip
284          *    synchronization
285          * Solution : resample the buffer to avoid a scratch.
286          */
287         mtime_t drift = p_buffer->start_date - start_date;
288
289         p_input->i_resamp_start_date = mdate();
290         p_input->i_resamp_start_drift = (int)drift;
291
292         if ( drift > 0 )
293             p_input->i_resampling_type = AOUT_RESAMPLING_DOWN;
294         else
295             p_input->i_resampling_type = AOUT_RESAMPLING_UP;
296
297         msg_Warn( p_aout, "buffer is "I64Fd" %s, triggering %ssampling",
298                           drift > 0 ? drift : -drift,
299                           drift > 0 ? "in advance" : "late",
300                           drift > 0 ? "down" : "up");
301     }
302
303     if ( p_input->i_resampling_type != AOUT_RESAMPLING_NONE )
304     {
305         /* Resampling has been triggered previously (because of dates
306          * mismatch). We want the resampling to happen progressively so
307          * it isn't too audible to the listener. */
308
309         if( p_input->i_resampling_type == AOUT_RESAMPLING_UP )
310         {
311             p_input->pp_resamplers[0]->input.i_rate += 10; /* Hz */
312         }
313         else
314         {
315             p_input->pp_resamplers[0]->input.i_rate -= 10; /* Hz */
316         }
317
318         /* Check if everything is back to normal, in which case we can stop the
319          * resampling */
320         if( p_input->pp_resamplers[0]->input.i_rate ==
321               p_input->input.i_rate )
322         {
323             p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
324             msg_Warn( p_aout, "resampling stopped after "I64Fi" usec",
325                       mdate() - p_input->i_resamp_start_date );
326         }
327         else if( abs( (int)(p_buffer->start_date - start_date) ) <
328                  abs( p_input->i_resamp_start_drift ) / 2 )
329         {
330             /* if we reduced the drift from half, then it is time to switch
331              * back the resampling direction. */
332             if( p_input->i_resampling_type == AOUT_RESAMPLING_UP )
333                 p_input->i_resampling_type = AOUT_RESAMPLING_DOWN;
334             else
335                 p_input->i_resampling_type = AOUT_RESAMPLING_UP;
336             p_input->i_resamp_start_drift = 0;
337         }
338         else if( p_input->i_resamp_start_drift &&
339                  ( abs( (int)(p_buffer->start_date - start_date) ) >
340                    abs( p_input->i_resamp_start_drift ) * 3 / 2 ) )
341         {
342             /* If the drift is increasing and not decreasing, than something
343              * is bad. We'd better stop the resampling right now. */
344             msg_Warn( p_aout, "timing screwed, stopping resampling" );
345             p_input->i_resampling_type = AOUT_RESAMPLING_NONE;
346             p_input->pp_resamplers[0]->input.i_rate = p_input->input.i_rate;
347         }
348     }
349
350     /* Adding the start date will be managed by aout_FifoPush(). */
351     p_buffer->end_date = start_date +
352         (p_buffer->end_date - p_buffer->start_date);
353     p_buffer->start_date = start_date;
354
355     /* Actually run the resampler now. */
356     if ( p_input->i_nb_resamplers > 0 && p_aout->mixer.mixer.i_rate !=
357          p_input->pp_resamplers[0]->input.i_rate )
358     {
359         aout_FiltersPlay( p_aout, p_input->pp_resamplers,
360                           p_input->i_nb_resamplers,
361                           &p_buffer );
362     }
363
364     vlc_mutex_lock( &p_aout->input_fifos_lock );
365     aout_FifoPush( p_aout, &p_input->fifo, p_buffer );
366     vlc_mutex_unlock( &p_aout->input_fifos_lock );
367
368     return 0;
369 }