]> git.sesse.net Git - vlc/blob - src/audio_output/aout_ext-dec.c
69cec970847b351225606276366638ecab04c3cf
[vlc] / src / audio_output / aout_ext-dec.c
1 /*****************************************************************************
2  * aout_ext-dec.c : exported fifo management functions
3  *****************************************************************************
4  * Copyright (C) 1999-2001 VideoLAN
5  * $Id: aout_ext-dec.c,v 1.15 2002/05/18 15:51:37 gbazin Exp $
6  *
7  * Authors: Michel Kaempf <maxx@via.ecp.fr>
8  *          Cyril Deguet <asmax@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdio.h>                                           /* "intf_msg.h" */
29 #include <stdlib.h>                            /* calloc(), malloc(), free() */
30 #include <string.h>
31
32 #include <videolan/vlc.h>
33
34 #include "audio_output.h"
35
36 /*****************************************************************************
37  * aout_CreateFifo
38  *****************************************************************************/
39 aout_fifo_t * aout_CreateFifo( int i_format, int i_channels, int i_rate,
40                                int i_frame_size, void *p_buffer )
41 {
42     aout_thread_t *p_aout;
43     aout_fifo_t   *p_fifo = NULL;
44     int i_index;
45
46     /* Spawn an audio output if there is none */
47     vlc_mutex_lock( &p_aout_bank->lock );
48
49     if( p_aout_bank->i_count == 0 )
50     {
51         intf_WarnMsg( 1, "aout: no aout present, spawning one" );
52
53         p_aout = aout_CreateThread( NULL, i_channels, i_rate );
54
55         /* Everything failed */
56         if( p_aout == NULL )
57         {
58             vlc_mutex_unlock( &p_aout_bank->lock );
59             return NULL;
60         }
61
62         p_aout_bank->pp_aout[ p_aout_bank->i_count ] = p_aout;
63         p_aout_bank->i_count++;
64     }
65     /* temporary hack to switch output type (mainly for spdif)
66      * FIXME: to be adapted when several output are available */
67     else if( p_aout_bank->pp_aout[0]->fifo[0].i_format != i_format )
68     {
69         intf_WarnMsg( 1, "aout: changing aout type" );
70
71         aout_DestroyThread( p_aout_bank->pp_aout[0], NULL );
72
73         p_aout = aout_CreateThread( NULL, i_channels, i_rate );
74
75         /* Everything failed */
76         if( p_aout == NULL )
77         {
78             vlc_mutex_unlock( &p_aout_bank->lock );
79             return NULL;
80         }
81
82         p_aout_bank->pp_aout[0] = p_aout;
83     }
84     else
85     {
86         /* Take the first audio output FIXME: take the best one */
87         p_aout = p_aout_bank->pp_aout[ 0 ];
88     }
89
90     /* Take the fifos lock */
91     vlc_mutex_lock( &p_aout->fifos_lock );
92
93     /* Look for a free fifo structure */
94     for( i_index = 0; i_index < AOUT_MAX_FIFOS; i_index++ )
95     {
96         if( p_aout->fifo[i_index].i_format == AOUT_FIFO_NONE )
97         {
98             p_fifo = &p_aout->fifo[i_index];
99             p_fifo->i_fifo = i_index;
100             break;
101         }
102     }
103
104     if( p_fifo == NULL )
105     {
106         intf_ErrMsg( "aout error: no fifo available" );
107         vlc_mutex_unlock( &p_aout->fifos_lock );
108         vlc_mutex_unlock( &p_aout_bank->lock );
109         return( NULL );
110     }
111
112     /* Initialize the new fifo structure */
113     switch ( p_fifo->i_format = i_format )
114     {
115         case AOUT_FIFO_PCM:
116         case AOUT_FIFO_SPDIF:
117             p_fifo->b_die = 0;
118
119             p_fifo->i_channels = i_channels;
120             p_fifo->i_rate = i_rate;
121             p_fifo->i_frame_size = i_frame_size;
122
123             p_fifo->i_unit_limit = (AOUT_FIFO_SIZE + 1)
124                                      * (i_frame_size / i_channels);
125
126             /* Allocate the memory needed to store the audio frames and their
127              * dates. As the fifo is a rotative fifo, we must be able to find
128              * out whether the fifo is full or empty, that's why we must in
129              * fact allocate memory for (AOUT_FIFO_SIZE+1) audio frames. */
130             p_fifo->date = malloc( ( sizeof(s16) * i_frame_size 
131                                       + sizeof(mtime_t) )
132                                    * ( AOUT_FIFO_SIZE + 1 ) );
133             if ( p_fifo->date == NULL )
134             {
135                 intf_ErrMsg( "aout error: cannot create fifo data" );
136                 p_fifo->i_format = AOUT_FIFO_NONE;
137                 vlc_mutex_unlock( &p_aout->fifos_lock );
138                 vlc_mutex_unlock( &p_aout_bank->lock );
139                 return( NULL );
140             }
141
142             p_fifo->buffer = (u8 *)p_fifo->date + sizeof(mtime_t)
143                                                      * ( AOUT_FIFO_SIZE + 1 );
144
145             /* Set the fifo's buffer as empty (the first frame that is to be
146              * played is also the first frame that is not to be played) */
147             p_fifo->i_start_frame = 0;
148             /* p_fifo->i_next_frame = 0; */
149             p_fifo->i_end_frame = 0;
150
151             /* Waiting for the audio decoder to compute enough frames to work
152              * out the fifo's current rate (as soon as the decoder has decoded
153              * enough frames, the members of the fifo structure that are not
154              * initialized now will be calculated) */
155             p_fifo->b_start_frame = 0;
156             p_fifo->b_next_frame = 0;
157             break;
158
159         default:
160             intf_ErrMsg( "aout error: unknown fifo type 0x%x",
161                          p_fifo->i_format );
162             p_fifo->i_format = AOUT_FIFO_NONE;
163             vlc_mutex_unlock( &p_aout->fifos_lock );
164             vlc_mutex_unlock( &p_aout_bank->lock );
165             return( NULL );
166     }
167
168     /* Release the fifos lock */
169     vlc_mutex_unlock( &p_aout->fifos_lock );
170     vlc_mutex_unlock( &p_aout_bank->lock );
171
172     intf_WarnMsg( 2, "aout info: fifo #%i allocated, %i channels, rate %li, "
173                      "frame size %i", p_fifo->i_fifo, p_fifo->i_channels,
174                      p_fifo->i_rate, p_fifo->i_frame_size );
175
176     /* Return the pointer to the fifo structure */
177     return( p_fifo );
178 }
179
180 /*****************************************************************************
181  * aout_DestroyFifo
182  *****************************************************************************/
183 void aout_DestroyFifo( aout_fifo_t * p_fifo )
184 {
185     intf_WarnMsg( 2, "aout info: fifo #%i destroyed", p_fifo->i_fifo );
186
187     vlc_mutex_lock( &p_fifo->data_lock );
188     p_fifo->b_die = 1;
189     vlc_mutex_unlock( &p_fifo->data_lock );
190 }
191
192 /*****************************************************************************
193  * aout_FreeFifo
194  *****************************************************************************/
195 void aout_FreeFifo( aout_fifo_t * p_fifo )
196 {
197     switch ( p_fifo->i_format )
198     {
199         case AOUT_FIFO_NONE:
200
201             break;
202
203         case AOUT_FIFO_PCM:
204         case AOUT_FIFO_SPDIF:
205
206             free( p_fifo->date );
207             p_fifo->i_format = AOUT_FIFO_NONE;
208
209             break;
210
211         default:
212
213             break;
214     }
215 }
216