]> git.sesse.net Git - vlc/blob - src/audio_output/input.c
Audio output 3. Expect major breakages.
[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.1 2002/08/07 21:36:56 massiot 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 #include "audio_output.h"
33 #include "aout_internal.h"
34
35 /*****************************************************************************
36  * aout_InputNew : allocate a new input and rework the filter pipeline
37  *****************************************************************************/
38 static aout_input_t * InputNew( aout_instance_t * p_aout,
39                                 audio_sample_format_t * p_format )
40 {
41     aout_input_t *  p_input = malloc(sizeof(aout_input_t));
42
43     if ( p_input == NULL ) return NULL;
44
45     vlc_mutex_lock( &p_aout->mixer_lock );
46     while ( p_aout->b_mixer_active )
47     {
48         vlc_cond_wait( &p_aout->mixer_signal, &p_aout->mixer_lock );
49     }
50
51     if ( p_aout->i_nb_inputs == 0 )
52     {
53         /* Recreate the output using the new format. */
54         if ( aout_OutputNew( p_aout, p_format ) < 0 )
55         {
56             free( p_input );
57             return NULL;
58         }
59     }
60     else
61     {
62         aout_MixerDelete( p_aout );
63     }
64
65     memcpy( &p_input->input, p_format,
66             sizeof(audio_sample_format_t) );
67
68     /* Prepare FIFO. */
69     aout_FifoInit( p_aout, &p_input->fifo );
70     p_input->p_first_byte_to_mix = NULL;
71
72     /* Create filters. */
73     if ( aout_FiltersCreatePipeline( p_aout, p_input->pp_filters,
74                                      &p_input->i_nb_filters, &p_input->input,
75                                      &p_aout->mixer.input ) < 0 )
76     {
77         msg_Err( p_aout, "couldn't set an input pipeline" );
78
79         aout_FifoDestroy( p_aout, &p_input->fifo );
80
81         free( p_input );
82
83         if ( !p_aout->i_nb_inputs )
84         {
85             aout_OutputDelete( p_aout );
86         }
87         return NULL;
88     }
89
90     p_aout->pp_inputs[p_aout->i_nb_inputs] = p_input;
91     p_aout->i_nb_inputs++;
92
93     if ( aout_MixerNew( p_aout ) < 0 )
94     {
95         p_aout->i_nb_inputs--;
96         aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters,
97                                      p_input->i_nb_filters );
98         aout_FifoDestroy( p_aout, &p_input->fifo );
99
100         free( p_input );
101
102         if ( !p_aout->i_nb_inputs )
103         {
104             aout_OutputDelete( p_aout );
105         }   
106     }
107
108     /* Prepare hints for the buffer allocator. */
109     p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
110     p_input->input_alloc.i_bytes_per_sec = -1;
111
112     aout_FiltersHintBuffers( p_aout, p_input->pp_filters,
113                              p_input->i_nb_filters,
114                              &p_input->input_alloc );
115
116     /* i_bytes_per_sec is still == -1 if no filters */
117     p_input->input_alloc.i_bytes_per_sec = __MAX(
118                                     p_input->input_alloc.i_bytes_per_sec,
119                                     aout_FormatToBytes( &p_input->input )
120                                      * p_input->input.i_rate );
121     /* Allocate in the heap, it is more convenient for the decoder. */
122     p_input->input_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
123
124     vlc_mutex_unlock( &p_aout->mixer_lock );
125
126     msg_Dbg( p_aout, "input 0x%x created", p_input );
127     return p_input;
128 }
129
130 aout_input_t * __aout_InputNew( vlc_object_t * p_this,
131                                 aout_instance_t ** pp_aout,
132                                 audio_sample_format_t * p_format )
133 {
134     /* Create an audio output if there is none. */
135     *pp_aout = vlc_object_find( p_this, VLC_OBJECT_AOUT, FIND_ANYWHERE );
136
137     if( *pp_aout == NULL )
138     {
139         msg_Dbg( p_this, "no aout present, spawning one" );
140
141         *pp_aout = aout_NewInstance( p_this );
142         /* Everything failed, I'm a loser, I just wanna die */
143         if( *pp_aout == NULL )
144         {
145             return NULL;
146         }
147     }
148     else
149     {
150         vlc_object_release( *pp_aout );
151     }
152
153     return InputNew( *pp_aout, p_format );
154 }
155
156 /*****************************************************************************
157  * aout_InputDelete : delete an input
158  *****************************************************************************/
159 void aout_InputDelete( aout_instance_t * p_aout, aout_input_t * p_input )
160 {
161     int i_input;
162
163     msg_Dbg( p_aout, "input 0x%x destroyed", p_input );
164
165     vlc_mutex_lock( &p_aout->mixer_lock );
166     while ( p_aout->b_mixer_active )
167     {
168         vlc_cond_wait( &p_aout->mixer_signal, &p_aout->mixer_lock );
169     }
170
171     for ( i_input = 0; i_input < p_aout->i_nb_inputs; i_input++ )
172     {
173         if ( p_aout->pp_inputs[i_input] == p_input )
174         {
175             break;
176         }
177     }
178
179     if ( i_input == p_aout->i_nb_inputs )
180     {
181         msg_Err( p_aout, "cannot find an input to delete" );
182         return;
183     }
184
185     /* Remove the input from the list. */
186     memmove( &p_aout->pp_inputs[i_input], &p_aout->pp_inputs[i_input + 1],
187              (AOUT_MAX_INPUTS - i_input - 1) * sizeof(aout_input_t *) );
188     p_aout->i_nb_inputs--;
189
190     vlc_mutex_unlock( &p_aout->mixer_lock );
191
192     aout_FiltersDestroyPipeline( p_aout, p_input->pp_filters,
193                                  p_input->i_nb_filters );
194     aout_FifoDestroy( p_aout, &p_input->fifo );
195
196     free( p_input );
197
198     if ( !p_aout->i_nb_inputs )
199     {
200         aout_OutputDelete( p_aout );
201         aout_MixerDelete( p_aout );
202     }
203 }
204
205 /*****************************************************************************
206  * aout_InputPlay : play a buffer
207  *****************************************************************************/
208 void aout_InputPlay( aout_instance_t * p_aout, aout_input_t * p_input,
209                      aout_buffer_t * p_buffer )
210 {
211     vlc_mutex_lock( &p_aout->input_lock );
212     while( p_aout->b_change_requested )
213     {
214         vlc_cond_wait( &p_aout->input_signal, &p_aout->input_lock );
215     }
216     p_aout->i_inputs_active++;
217     vlc_mutex_unlock( &p_aout->input_lock );
218
219     aout_FiltersPlay( p_aout, p_input->pp_filters, p_input->i_nb_filters,
220                       &p_buffer );
221
222     aout_FifoPush( p_aout, &p_input->fifo, p_buffer );
223
224     vlc_mutex_lock( &p_aout->input_lock );
225     p_aout->i_inputs_active--;
226     vlc_cond_broadcast( &p_aout->input_signal );
227     vlc_mutex_unlock( &p_aout->input_lock );
228 }