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