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