]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
a5d3ce568ba17ff986b0f51ab6e8b70415020127
[vlc] / src / audio_output / audio_output.c
1 /*****************************************************************************
2  * audio_output.c : audio output thread
3  *****************************************************************************
4  * Copyright (C) 1999, 2000 VideoLAN
5  *
6  * Authors: Michel Kaempf <maxx@via.ecp.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  * 
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21  *****************************************************************************/
22
23 /* TODO:
24  *
25  * - Passer un certain nombre de "fonctions" (genre add_samples) en macro ou
26  *   inline
27  * - Faire les optimisations dans les fonctions threads :
28  *   = Stocker les "petits calculs" dans des variables au lieu de les refaire
29  *     à chaque boucle
30  *   = Utiliser des tables pour les gros calculs
31  * - Faire une structure différente pour intf/adec fifo
32  *
33  */
34
35 /*****************************************************************************
36  * Preamble
37  *****************************************************************************/
38 #include "defs.h"
39
40 #include <unistd.h>                                              /* getpid() */
41
42 #include <stdio.h>                                           /* "intf_msg.h" */
43 #include <stdlib.h>                            /* calloc(), malloc(), free() */
44
45 #include "config.h"
46 #include "common.h"
47 #include "threads.h"
48 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
49 #include "plugins.h"
50 #include "modules.h"
51
52 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
53
54 #include "audio_output.h"
55 #include "main.h"
56
57 /*****************************************************************************
58  * Local prototypes
59  *****************************************************************************/
60
61 static int aout_SpawnThread( aout_thread_t * p_aout );
62
63 /* Creating as much aout_Thread functions as configurations is one solution,
64  * examining the different cases in the Thread loop of an unique function is
65  * another. I chose the first solution. */
66 void aout_Thread_S8_Mono        ( aout_thread_t * p_aout );
67 void aout_Thread_U8_Mono        ( aout_thread_t * p_aout );
68 void aout_Thread_S16_Mono       ( aout_thread_t * p_aout );
69 void aout_Thread_U16_Mono       ( aout_thread_t * p_aout );
70 void aout_Thread_S8_Stereo      ( aout_thread_t * p_aout );
71 void aout_Thread_U8_Stereo      ( aout_thread_t * p_aout );
72 void aout_Thread_S16_Stereo     ( aout_thread_t * p_aout );
73 void aout_Thread_U16_Stereo     ( aout_thread_t * p_aout );
74
75 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
76 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date );
77
78 /*****************************************************************************
79  * InitializeIncrement
80  *****************************************************************************/
81 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
82 {
83     p_increment->l_remainder = -l_denominator;
84
85     p_increment->l_euclidean_integer = 0;
86     while ( l_numerator >= l_denominator )
87     {
88         p_increment->l_euclidean_integer++;
89         l_numerator -= l_denominator;
90     }
91
92     p_increment->l_euclidean_remainder = l_numerator;
93
94     p_increment->l_euclidean_denominator = l_denominator;
95 }
96
97 /*****************************************************************************
98  * aout_CreateThread: initialize audio thread
99  *****************************************************************************/
100 aout_thread_t *aout_CreateThread( int *pi_status )
101 {
102     aout_thread_t * p_aout;                             /* thread descriptor */
103 #if 0
104     int             i_status;                               /* thread status */
105 #endif
106
107     /* Allocate descriptor */
108     p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
109     if( p_aout == NULL )
110     {
111         return( NULL );
112     }
113
114     /* Choose the best module */
115     p_aout->p_module = module_Need( p_main->p_module_bank,
116                                     MODULE_CAPABILITY_AOUT, NULL );
117
118     if( p_aout->p_module == NULL )
119     {
120         intf_ErrMsg( "aout error: no suitable aout module" );
121         free( p_aout );
122         return( NULL );
123     }
124
125 #define aout_functions p_aout->p_module->p_functions->aout.functions.aout
126     p_aout->pf_open       = aout_functions.pf_open;
127     p_aout->pf_setformat  = aout_functions.pf_setformat;
128     p_aout->pf_getbufinfo = aout_functions.pf_getbufinfo;
129     p_aout->pf_play       = aout_functions.pf_play;
130     p_aout->pf_close      = aout_functions.pf_close;
131 #undef aout_functions
132
133     /*
134      * Initialize audio device
135      */
136     if ( p_aout->pf_open( p_aout ) )
137     {
138         module_Unneed( p_main->p_module_bank, p_aout->p_module );
139         free( p_aout );
140         return( NULL );
141     }
142
143     p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0; /* FIXME: only works
144                                                    for i_channels == 1 or 2 ??*/
145
146     if ( p_aout->pf_setformat( p_aout ) )
147     {
148         p_aout->pf_close( p_aout );
149         module_Unneed( p_main->p_module_bank, p_aout->p_module );
150         free( p_aout );
151         return( NULL );
152     }
153
154     /* Initialize the volume level */
155     p_aout->vol = VOLUME_DEFAULT;
156     
157     /* FIXME: maybe it would be cleaner to change SpawnThread prototype
158      * see vout to handle status correctly ?? however, it is not critical since
159      * this thread is only called in main and all calls are blocking */
160     if( aout_SpawnThread( p_aout ) )
161     {
162         p_aout->pf_close( p_aout );
163         module_Unneed( p_main->p_module_bank, p_aout->p_module );
164         free( p_aout );
165         return( NULL );
166     }
167
168     return( p_aout );
169 }
170
171 /*****************************************************************************
172  * aout_SpawnThread
173  *****************************************************************************/
174 static int aout_SpawnThread( aout_thread_t * p_aout )
175 {
176     int             i_fifo;
177     long            l_bytes;
178     void *          aout_thread = NULL;
179
180     intf_DbgMsg("aout debug: spawning audio output thread (%p)", p_aout);
181
182     /* We want the audio output thread to live */
183     p_aout->b_die = 0;
184     p_aout->b_active = 1;
185
186     /* Initialize the fifos lock */
187     vlc_mutex_init( &p_aout->fifos_lock );
188     /* Initialize audio fifos : set all fifos as empty and initialize locks */
189     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
190     {
191         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
192         vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
193         vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
194     }
195
196     /* Compute the size (in audio units) of the audio output buffer. Although
197      * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
198      * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
199     p_aout->l_units = (long)( ((s64)p_aout->l_rate * AOUT_BUFFER_DURATION) / 1000000 );
200     p_aout->l_msleep = (long)( ((s64)p_aout->l_units * 1000000) / (s64)p_aout->l_rate );
201
202     /* Make aout_thread point to the right thread function, and compute the
203      * byte size of the audio output buffer */
204     switch ( p_aout->i_channels )
205     {
206         /* Audio output is mono */
207         case 1:
208             switch ( p_aout->i_format )
209             {
210                 case AOUT_FMT_U8:
211                     l_bytes = 1 * sizeof(u8) * p_aout->l_units;
212                     aout_thread = (void *)aout_Thread_U8_Mono;
213                     break;
214
215                 case AOUT_FMT_S8:
216                     l_bytes = 1 * sizeof(s8) * p_aout->l_units;
217                     aout_thread = (void *)aout_Thread_S8_Mono;
218                     break;
219
220                 case AOUT_FMT_U16_LE:
221                 case AOUT_FMT_U16_BE:
222                     l_bytes = 1 * sizeof(u16) * p_aout->l_units;
223                     aout_thread = (void *)aout_Thread_U16_Mono;
224                     break;
225
226                 case AOUT_FMT_S16_LE:
227                 case AOUT_FMT_S16_BE:
228                     l_bytes = 1 * sizeof(s16) * p_aout->l_units;
229                     aout_thread = (void *)aout_Thread_S16_Mono;
230                     break;
231
232                 default:
233                     intf_ErrMsg( "aout error: unknown audio output format (%i)",
234                                  p_aout->i_format );
235                     return( -1 );
236             }
237             break;
238
239         /* Audio output is stereo */
240         case 2:
241             switch ( p_aout->i_format )
242             {
243                 case AOUT_FMT_U8:
244                     l_bytes = 2 * sizeof(u8) * p_aout->l_units;
245                     aout_thread = (void *)aout_Thread_U8_Stereo;
246                     break;
247
248                 case AOUT_FMT_S8:
249                     l_bytes = 2 * sizeof(s8) * p_aout->l_units;
250                     aout_thread = (void *)aout_Thread_S8_Stereo;
251                     break;
252
253                 case AOUT_FMT_U16_LE:
254                 case AOUT_FMT_U16_BE:
255                     l_bytes = 2 * sizeof(u16) * p_aout->l_units;
256                     aout_thread = (void *)aout_Thread_U16_Stereo;
257                     break;
258
259                 case AOUT_FMT_S16_LE:
260                 case AOUT_FMT_S16_BE:
261                     l_bytes = 2 * sizeof(s16) * p_aout->l_units;
262                     aout_thread = (void *)aout_Thread_S16_Stereo;
263                     break;
264
265                 default:
266                     intf_ErrMsg("aout error: unknown audio output format (%i)",
267                         p_aout->i_format);
268                     return( -1 );
269             }
270             break;
271
272         default:
273             intf_ErrMsg("aout error: unknown number of audio channels (%i)",
274                 p_aout->i_channels );
275             return( -1 );
276     }
277
278     /* Allocate the memory needed by the audio output buffers, and set to zero
279      * the s32 buffer's memory */
280     if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
281     {
282         intf_ErrMsg("aout error: not enough memory to create the output buffer");
283         return( -1 );
284     }
285     if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << ( p_aout->b_stereo))) == NULL )
286     {
287         intf_ErrMsg("aout error: not enough memory to create the s32 output buffer");
288         free( p_aout->buffer );
289         return( -1 );
290     }
291
292     /* Before launching the thread, we try to predict the date of the first
293      * audio unit in the first output buffer */
294     p_aout->date = mdate() - 1000000;
295
296     /* Launch the thread */
297     if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
298     {
299         intf_ErrMsg("aout error: can't spawn audio output thread (%p)", p_aout);
300         free( p_aout->buffer );
301         free( p_aout->s32_buffer );
302         return( -1 );
303     }
304
305     intf_DbgMsg("aout debug: audio output thread (%p) spawned", p_aout);
306     return( 0 );
307 }
308
309 /*****************************************************************************
310  * aout_DestroyThread
311  *****************************************************************************/
312 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
313 {
314
315     int i_fifo;
316     
317     /* FIXME: pi_status is not handled correctly: check vout how to do!?? */
318
319     intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)", p_aout);
320
321     /* Ask thread to kill itself and wait until it's done */
322     p_aout->b_die = 1;
323     vlc_thread_join( p_aout->thread_id ); /* only if pi_status is NULL */
324
325     /* Free the allocated memory */
326     free( p_aout->buffer );
327     free( p_aout->s32_buffer );
328
329     /* Destroy the condition and mutex locks */
330     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
331     {
332         vlc_mutex_destroy( &p_aout->fifo[i_fifo].data_lock );
333         vlc_cond_destroy( &p_aout->fifo[i_fifo].data_wait );
334     }
335     vlc_mutex_destroy( &p_aout->fifos_lock );
336     
337     /* Free the plugin */
338     p_aout->pf_close( p_aout );
339
340     /* Release the aout module */
341     module_Unneed( p_main->p_module_bank, p_aout->p_module );
342
343     /* Free structure */
344     free( p_aout );
345 }
346
347 /*****************************************************************************
348  * aout_CreateFifo
349  *****************************************************************************/
350 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
351 {
352     int i_fifo;
353
354     /* Take the fifos lock */
355     vlc_mutex_lock( &p_aout->fifos_lock );
356
357     /* Looking for a free fifo structure */
358     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
359     {
360         if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
361         {
362             break;
363         }
364     }
365     if ( i_fifo == AOUT_MAX_FIFOS )
366     {
367         intf_ErrMsg("aout error: no empty fifo available");
368         vlc_mutex_unlock( &p_aout->fifos_lock );
369         return( NULL );
370     }
371
372     /* Initialize the new fifo structure */
373     switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
374     {
375         case AOUT_INTF_MONO_FIFO:
376         case AOUT_INTF_STEREO_FIFO:
377             p_aout->fifo[i_fifo].b_die = 0;
378
379             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
380             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
381             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
382
383             p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
384
385             p_aout->fifo[i_fifo].l_unit = 0;
386             InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->l_rate );
387             p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
388             break;
389
390         case AOUT_ADEC_MONO_FIFO:
391         case AOUT_ADEC_STEREO_FIFO:
392             p_aout->fifo[i_fifo].b_die = 0;
393
394             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
395             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
396             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
397
398             p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
399             /* Allocate the memory needed to store the audio frames. As the
400              * fifo is a rotative fifo, we must be able to find out whether the
401              * fifo is full or empty, that's why we must in fact allocate memory
402              * for (AOUT_FIFO_SIZE+1) audio frames. */
403             if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
404             {
405                 intf_ErrMsg("aout error: not enough memory to create the frames buffer");
406                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
407                 vlc_mutex_unlock( &p_aout->fifos_lock );
408                 return( NULL );
409             }
410
411             /* Allocate the memory needed to store the dates of the frames */
412             if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
413             {
414                 intf_ErrMsg("aout error: not enough memory to create the dates buffer");
415                 free( p_aout->fifo[i_fifo].buffer );
416                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
417                 vlc_mutex_unlock( &p_aout->fifos_lock );
418                 return( NULL );
419             }
420
421             /* Set the fifo's buffer as empty (the first frame that is to be
422              * played is also the first frame that is not to be played) */
423             p_aout->fifo[i_fifo].l_start_frame = 0;
424             /* p_aout->fifo[i_fifo].l_next_frame = 0; */
425             p_aout->fifo[i_fifo].l_end_frame = 0;
426
427             /* Waiting for the audio decoder to compute enough frames to work
428              * out the fifo's current rate (as soon as the decoder has decoded
429              * enough frames, the members of the fifo structure that are not
430              * initialized now will be calculated) */
431             p_aout->fifo[i_fifo].b_start_frame = 0;
432             p_aout->fifo[i_fifo].b_next_frame = 0;
433             break;
434
435         default:
436             intf_ErrMsg("aout error: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
437             p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
438             vlc_mutex_unlock( &p_aout->fifos_lock );
439             return( NULL );
440     }
441
442     /* Release the fifos lock */
443     vlc_mutex_unlock( &p_aout->fifos_lock );
444
445     /* Return the pointer to the fifo structure */
446     intf_DbgMsg("aout debug: audio output fifo (%p) allocated", &p_aout->fifo[i_fifo]);
447     return( &p_aout->fifo[i_fifo] );
448 }
449
450 /*****************************************************************************
451  * aout_DestroyFifo
452  *****************************************************************************/
453 void aout_DestroyFifo( aout_fifo_t * p_fifo )
454 {
455     intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)", p_fifo);
456     p_fifo->b_die = 1;
457 }
458
459 /* Here are the local macros */
460
461 #define UPDATE_INCREMENT( increment, integer ) \
462     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
463     { \
464         (integer) += (increment).l_euclidean_integer + 1; \
465         (increment).l_remainder -= (increment).l_euclidean_denominator; \
466     } \
467     else \
468     { \
469         (integer) += (increment).l_euclidean_integer; \
470     }
471
472 /* Following functions are local */
473
474 /*****************************************************************************
475  * NextFrame
476  *****************************************************************************/
477 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date )
478 {
479     long l_units, l_rate;
480
481     /* We take the lock */
482     vlc_mutex_lock( &p_fifo->data_lock );
483
484     /* Are we looking for a dated start frame ? */
485     if ( !p_fifo->b_start_frame )
486     {
487         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
488         {
489             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
490             {
491                 p_fifo->b_start_frame = 1;
492                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
493                 p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
494                 break;
495             }
496             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
497         }
498
499         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
500         {
501             vlc_mutex_unlock( &p_fifo->data_lock );
502             return( -1 );
503         }
504     }
505
506     /* We are looking for the next dated frame */
507     /* FIXME : is the output fifo full ?? */
508     while ( !p_fifo->b_next_frame )
509     {
510         while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
511         {
512             if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
513             {
514                 p_fifo->b_next_frame = 1;
515                 break;
516             }
517             p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
518         }
519
520         while ( p_fifo->l_next_frame == p_fifo->l_end_frame )
521         {
522             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
523             if ( p_fifo->b_die )
524             {
525                 vlc_mutex_unlock( &p_fifo->data_lock );
526                 return( -1 );
527             }
528         }
529     }
530
531     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
532
533     l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
534     intf_DbgMsg( "aout debug: %lli (%li);", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
535
536     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->l_rate );
537
538     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
539         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo)))))
540         * p_aout->l_rate) / l_rate) + 1;
541
542     /* We release the lock before leaving */
543     vlc_mutex_unlock( &p_fifo->data_lock );
544     return( 0 );
545 }
546
547 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
548 {
549 }
550
551 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
552 {
553 }
554
555 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
556 {
557     int i_fifo;
558     long l_buffer, l_buffer_limit;
559     long l_units, l_bytes;
560
561     intf_DbgMsg("adec debug: running audio output U8_M_thread (%p) (pid == %i)", p_aout, getpid());
562
563     /* As the s32_buffer was created with calloc(), we don't have to set this
564      * memory to zero and we can immediately jump into the thread's loop */
565     while ( !p_aout->b_die )
566     {
567         vlc_mutex_lock( &p_aout->fifos_lock );
568         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
569         {
570             switch ( p_aout->fifo[i_fifo].i_type )
571             {
572                 case AOUT_EMPTY_FIFO:
573                     break;
574
575                 case AOUT_INTF_MONO_FIFO:
576                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
577                     {
578                         l_buffer = 0;
579                         while ( l_buffer < (p_aout->l_units) ) /* p_aout->b_stereo == 0 */
580                         {
581                             p_aout->s32_buffer[l_buffer++] +=
582                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
583                             p_aout->s32_buffer[l_buffer++] +=
584                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
585                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
586                         }
587                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
588                     }
589                     else
590                     {
591                         l_buffer = 0;
592                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units) ) /* p_aout->b_stereo == 0 */
593                         {
594                             p_aout->s32_buffer[l_buffer++] +=
595                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
596                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
597                         }
598                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
599                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
600                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
601                     }
602                     break;
603
604                 case AOUT_INTF_STEREO_FIFO:
605                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
606                     {
607                         l_buffer = 0;
608                         while ( l_buffer < (p_aout->l_units) ) /* p_aout->b_stereo == 0 */
609                         {
610                             /* I mix half left - half right */
611                             p_aout->s32_buffer[l_buffer++] +=
612                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
613                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
614                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
615                         }
616                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
617                     }
618                     else
619                     {
620                         l_buffer = 0;
621                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units) ) /* p_aout->b_stereo == 0 */
622                         {
623                             /* I mix half left - half right */
624                             p_aout->s32_buffer[l_buffer++] +=
625                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
626                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
627                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
628                         }
629                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
630                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
631                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
632                     }
633                     break;
634
635                 case AOUT_ADEC_MONO_FIFO:
636                     if ( p_aout->fifo[i_fifo].b_die )
637                     {
638                         free( p_aout->fifo[i_fifo].buffer );
639                         free( p_aout->fifo[i_fifo].date );
640                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
641                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
642                         continue;
643                     }
644
645                     l_units = p_aout->l_units;
646                     l_buffer = 0;
647                     while ( l_units > 0 )
648                     {
649                         if ( !p_aout->fifo[i_fifo].b_next_frame )
650                         {
651                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
652                             {
653                                 break;
654                             }
655                         }
656
657                         if ( p_aout->fifo[i_fifo].l_units > l_units )
658                         {
659                             l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
660                             while ( l_buffer < l_buffer_limit )
661                             {
662                                 p_aout->s32_buffer[l_buffer++] +=
663                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
664
665                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
666                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
667                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
668                                 {
669                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
670                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
671                                 }
672                             }
673                             p_aout->fifo[i_fifo].l_units -= l_units;
674                             break;
675                         }
676                         else
677                         {
678                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units);
679                             /* p_aout->b_stereo == 0 */
680                             while ( l_buffer < l_buffer_limit )
681                             {
682                                 p_aout->s32_buffer[l_buffer++] +=
683                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
684
685                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
686                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
687                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
688                                 {
689                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
690                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
691                                 }
692                             }
693                             l_units -= p_aout->fifo[i_fifo].l_units;
694
695                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
696                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
697                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
698                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
699
700                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
701                             p_aout->fifo[i_fifo].l_next_frame += 1;
702                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
703                             p_aout->fifo[i_fifo].b_next_frame = 0;
704                         }
705                     }
706                     break;
707
708                 case AOUT_ADEC_STEREO_FIFO:
709                     if ( p_aout->fifo[i_fifo].b_die )
710                     {
711                         free( p_aout->fifo[i_fifo].buffer );
712                         free( p_aout->fifo[i_fifo].date );
713                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
714                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
715                         continue;
716                     }
717
718                     l_units = p_aout->l_units;
719                     l_buffer = 0;
720                     while ( l_units > 0 )
721                     {
722                         if ( !p_aout->fifo[i_fifo].b_next_frame )
723                         {
724                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
725                             {
726                                 break;
727                             }
728                         }
729
730                         if ( p_aout->fifo[i_fifo].l_units > l_units )
731                         {
732                             l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
733                             while ( l_buffer < l_buffer_limit )
734                             {
735                                 /* I mix half left - half right */
736                                 p_aout->s32_buffer[l_buffer++] +=
737                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
738                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
739
740                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
741                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
742                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
743                                 {
744                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
745                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
746                                 }
747                             }
748                             p_aout->fifo[i_fifo].l_units -= l_units;
749                             break;
750                         }
751                         else
752                         {
753                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units);
754                             /* p_aout->b_stereo == 0 */
755                             while ( l_buffer < l_buffer_limit )
756                             {
757                                 /* I mix half left - half right */
758                                 p_aout->s32_buffer[l_buffer++] +=
759                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
760                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
761
762                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
763                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
764                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
765                                 {
766                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
767                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
768                                 }
769                             }
770                             l_units -= p_aout->fifo[i_fifo].l_units;
771
772                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
773                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
774                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
775                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
776
777                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
778                             p_aout->fifo[i_fifo].l_next_frame += 1;
779                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
780                             p_aout->fifo[i_fifo].b_next_frame = 0;
781                         }
782                     }
783                     break;
784
785             default:
786                     intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
787                     break;
788             }
789         }
790         vlc_mutex_unlock( &p_aout->fifos_lock );
791
792         l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
793
794         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
795         {
796             ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256 ) + 128 ) * p_aout->vol / 256 );
797             p_aout->s32_buffer[l_buffer] = 0;
798         }
799         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
800         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 1 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 1 */
801         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
802         if ( l_bytes > (l_buffer_limit * sizeof(u8) * 2) ) /* There are 2 channels (left & right) */
803         {
804             msleep( p_aout->l_msleep );
805         }
806     }
807
808     vlc_mutex_lock( &p_aout->fifos_lock );
809     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
810     {
811         switch ( p_aout->fifo[i_fifo].i_type )
812         {
813             case AOUT_EMPTY_FIFO:
814                 break;
815
816             case AOUT_INTF_MONO_FIFO:
817             case AOUT_INTF_STEREO_FIFO:
818                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
819                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
820                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
821                 break;
822
823             case AOUT_ADEC_MONO_FIFO:
824             case AOUT_ADEC_STEREO_FIFO:
825                 free( p_aout->fifo[i_fifo].buffer );
826                 free( p_aout->fifo[i_fifo].date );
827                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
828                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
829                 break;
830
831             default:
832                 break;
833         }
834     }
835     vlc_mutex_unlock( &p_aout->fifos_lock );
836
837
838 }
839
840 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
841 {
842     int i_fifo;
843     long l_buffer, l_buffer_limit;
844     long l_units, l_bytes;
845
846     intf_DbgMsg("adec debug: running audio output U8_S_thread (%p) (pid == %i)", p_aout, getpid());
847
848     /* As the s32_buffer was created with calloc(), we don't have to set this
849      * memory to zero and we can immediately jump into the thread's loop */
850     while ( !p_aout->b_die )
851     {
852         vlc_mutex_lock( &p_aout->fifos_lock );
853         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
854         {
855             switch ( p_aout->fifo[i_fifo].i_type )
856             {
857                 case AOUT_EMPTY_FIFO:
858                     break;
859
860                 case AOUT_INTF_MONO_FIFO:
861                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
862                     {
863                         l_buffer = 0;
864                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
865                         {
866                             p_aout->s32_buffer[l_buffer++] +=
867                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
868                             p_aout->s32_buffer[l_buffer++] +=
869                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
870                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
871                         }
872                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
873                     }
874                     else
875                     {
876                         l_buffer = 0;
877                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
878                         {
879                             p_aout->s32_buffer[l_buffer++] +=
880                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
881                             p_aout->s32_buffer[l_buffer++] +=
882                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
883                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
884                         }
885                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
886                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
887                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
888                     }
889                     break;
890
891                 case AOUT_INTF_STEREO_FIFO:
892                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
893                     {
894                         l_buffer = 0;
895                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
896                         {
897                             p_aout->s32_buffer[l_buffer++] +=
898                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
899                             p_aout->s32_buffer[l_buffer++] +=
900                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
901                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
902                         }
903                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
904                     }
905                     else
906                     {
907                         l_buffer = 0;
908                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
909                         {
910                             p_aout->s32_buffer[l_buffer++] +=
911                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
912                             p_aout->s32_buffer[l_buffer++] +=
913                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
914                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
915                         }
916                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
917                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
918                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
919                     }
920                     break;
921
922                 case AOUT_ADEC_MONO_FIFO:
923                     if ( p_aout->fifo[i_fifo].b_die )
924                     {
925                         free( p_aout->fifo[i_fifo].buffer );
926                         free( p_aout->fifo[i_fifo].date );
927                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
928                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
929                         continue;
930                     }
931
932                     l_units = p_aout->l_units;
933                     l_buffer = 0;
934                     while ( l_units > 0 )
935                     {
936                         if ( !p_aout->fifo[i_fifo].b_next_frame )
937                         {
938                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
939                             {
940                                 break;
941                             }
942                         }
943
944                         if ( p_aout->fifo[i_fifo].l_units > l_units )
945                         {
946                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
947                             while ( l_buffer < l_buffer_limit )
948                             {
949                                 p_aout->s32_buffer[l_buffer++] +=
950                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
951                                 p_aout->s32_buffer[l_buffer++] +=
952                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
953
954                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
955                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
956                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
957                                 {
958                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
959                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
960                                 }
961                             }
962                             p_aout->fifo[i_fifo].l_units -= l_units;
963                             break;
964                         }
965                         else
966                         {
967                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
968                             /* p_aout->b_stereo == 1 */
969                             while ( l_buffer < l_buffer_limit )
970                             {
971                                 p_aout->s32_buffer[l_buffer++] +=
972                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
973                                 p_aout->s32_buffer[l_buffer++] +=
974                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
975
976                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
977                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
978                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
979                                 {
980                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
981                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
982                                 }
983                             }
984                             l_units -= p_aout->fifo[i_fifo].l_units;
985
986                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
987                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
988                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
989                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
990
991                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
992                             p_aout->fifo[i_fifo].l_next_frame += 1;
993                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
994                             p_aout->fifo[i_fifo].b_next_frame = 0;
995                         }
996                     }
997                     break;
998
999                 case AOUT_ADEC_STEREO_FIFO:
1000                     if ( p_aout->fifo[i_fifo].b_die )
1001                     {
1002                         free( p_aout->fifo[i_fifo].buffer );
1003                         free( p_aout->fifo[i_fifo].date );
1004                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1005                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1006                         continue;
1007                     }
1008
1009                     l_units = p_aout->l_units;
1010                     l_buffer = 0;
1011                     while ( l_units > 0 )
1012                     {
1013                         if ( !p_aout->fifo[i_fifo].b_next_frame )
1014                         {
1015                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
1016                             {
1017                                 break;
1018                             }
1019                         }
1020
1021                         if ( p_aout->fifo[i_fifo].l_units > l_units )
1022                         {
1023                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1024                             while ( l_buffer < l_buffer_limit )
1025                             {
1026                                 p_aout->s32_buffer[l_buffer++] +=
1027                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1028                                 p_aout->s32_buffer[l_buffer++] +=
1029                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1030
1031                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1032                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1033                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1034                                 {
1035                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1036                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1037                                 }
1038                             }
1039                             p_aout->fifo[i_fifo].l_units -= l_units;
1040                             break;
1041                         }
1042                         else
1043                         {
1044                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
1045                             /* p_aout->b_stereo == 1 */
1046                             while ( l_buffer < l_buffer_limit )
1047                             {
1048                                 p_aout->s32_buffer[l_buffer++] +=
1049                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1050                                 p_aout->s32_buffer[l_buffer++] +=
1051                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1052
1053                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1054                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1055                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1056                                 {
1057                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1058                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1059                                 }
1060                             }
1061                             l_units -= p_aout->fifo[i_fifo].l_units;
1062
1063                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1064                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1065                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1066                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1067
1068                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1069                             p_aout->fifo[i_fifo].l_next_frame += 1;
1070                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1071                             p_aout->fifo[i_fifo].b_next_frame = 0;
1072                         }
1073                     }
1074                     break;
1075
1076             default:
1077                     intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
1078                     break;
1079             }
1080         }
1081         vlc_mutex_unlock( &p_aout->fifos_lock );
1082
1083         l_buffer_limit = p_aout->l_units  << 1 ; /* p_aout->b_stereo == 1 */
1084
1085         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
1086         {
1087             ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256) + 128 ) * p_aout->vol / 256 );
1088             p_aout->s32_buffer[l_buffer] = 0;
1089         }
1090         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
1091         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 2 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 2 */
1092         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
1093         if ( l_bytes > (l_buffer_limit * sizeof(u8)) )
1094         {
1095             msleep( p_aout->l_msleep );
1096         }
1097     }
1098
1099     vlc_mutex_lock( &p_aout->fifos_lock );
1100     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
1101     {
1102         switch ( p_aout->fifo[i_fifo].i_type )
1103         {
1104             case AOUT_EMPTY_FIFO:
1105                 break;
1106
1107             case AOUT_INTF_MONO_FIFO:
1108             case AOUT_INTF_STEREO_FIFO:
1109                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
1110                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1111                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1112                 break;
1113
1114             case AOUT_ADEC_MONO_FIFO:
1115             case AOUT_ADEC_STEREO_FIFO:
1116                 free( p_aout->fifo[i_fifo].buffer );
1117                 free( p_aout->fifo[i_fifo].date );
1118                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1119                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1120                 break;
1121
1122             default:
1123                 break;
1124         }
1125     }
1126     vlc_mutex_unlock( &p_aout->fifos_lock );
1127
1128 }
1129
1130 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
1131 {
1132 }
1133
1134 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
1135 {
1136     int i_fifo;
1137     long l_buffer, l_buffer_limit;
1138     long l_units, l_bytes;
1139
1140     intf_DbgMsg("adec debug: running audio output S16_S_thread (%p) (pid == %i)", p_aout, getpid());
1141
1142     /* As the s32_buffer was created with calloc(), we don't have to set this
1143      * memory to zero and we can immediately jump into the thread's loop */
1144     while ( !p_aout->b_die )
1145     {
1146         vlc_mutex_lock( &p_aout->fifos_lock );
1147         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
1148         {
1149             switch ( p_aout->fifo[i_fifo].i_type )
1150             {
1151                 case AOUT_EMPTY_FIFO:
1152                     break;
1153
1154                 case AOUT_INTF_MONO_FIFO:
1155                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
1156                     {
1157                         l_buffer = 0;
1158                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
1159                         {
1160                             p_aout->s32_buffer[l_buffer++] +=
1161                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1162                             p_aout->s32_buffer[l_buffer++] +=
1163                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1164                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1165                         }
1166                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
1167                     }
1168                     else
1169                     {
1170                         l_buffer = 0;
1171                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
1172                         {
1173                             p_aout->s32_buffer[l_buffer++] +=
1174                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1175                             p_aout->s32_buffer[l_buffer++] +=
1176                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1177                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1178                         }
1179                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
1180                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1181                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
1182                     }
1183                     break;
1184
1185                 case AOUT_INTF_STEREO_FIFO:
1186                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
1187                     {
1188                         l_buffer = 0;
1189                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
1190                         {
1191                             p_aout->s32_buffer[l_buffer++] +=
1192                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1193                             p_aout->s32_buffer[l_buffer++] +=
1194                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1195                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1196                         }
1197                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
1198                     }
1199                     else
1200                     {
1201                         l_buffer = 0;
1202                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
1203                         {
1204                             p_aout->s32_buffer[l_buffer++] +=
1205                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1206                             p_aout->s32_buffer[l_buffer++] +=
1207                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1208                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1209                         }
1210                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
1211                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1212                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]); /* !! */
1213                     }
1214                     break;
1215
1216                 case AOUT_ADEC_MONO_FIFO:
1217                     if ( p_aout->fifo[i_fifo].b_die )
1218                     {
1219                         free( p_aout->fifo[i_fifo].buffer );
1220                         free( p_aout->fifo[i_fifo].date );
1221                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1222                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1223                         continue;
1224                     }
1225
1226                     l_units = p_aout->l_units;
1227                     l_buffer = 0;
1228                     while ( l_units > 0 )
1229                     {
1230                         if ( !p_aout->fifo[i_fifo].b_next_frame )
1231                         {
1232                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
1233                             {
1234                                 break;
1235                             }
1236                         }
1237
1238                         if ( p_aout->fifo[i_fifo].l_units > l_units )
1239                         {
1240                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1241                             while ( l_buffer < l_buffer_limit )
1242                             {
1243                                 p_aout->s32_buffer[l_buffer++] +=
1244                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1245                                 p_aout->s32_buffer[l_buffer++] +=
1246                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1247
1248                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1249                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1250                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
1251                                 {
1252                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1253                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
1254                                 }
1255                             }
1256                             p_aout->fifo[i_fifo].l_units -= l_units;
1257                             break;
1258                         }
1259                         else
1260                         {
1261                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
1262                             /* p_aout->b_stereo == 1 */
1263                             while ( l_buffer < l_buffer_limit )
1264                             {
1265                                 p_aout->s32_buffer[l_buffer++] +=
1266                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1267                                 p_aout->s32_buffer[l_buffer++] +=
1268                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
1269
1270                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1271                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1272                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
1273                                 {
1274                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1275                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
1276                                 }
1277                             }
1278                             l_units -= p_aout->fifo[i_fifo].l_units;
1279
1280                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1281                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1282                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1283                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1284
1285                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1286                             p_aout->fifo[i_fifo].l_next_frame += 1;
1287                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1288                             p_aout->fifo[i_fifo].b_next_frame = 0;
1289                         }
1290                     }
1291                     break;
1292
1293                 case AOUT_ADEC_STEREO_FIFO:
1294                     if ( p_aout->fifo[i_fifo].b_die )
1295                     {
1296                         free( p_aout->fifo[i_fifo].buffer );
1297                         free( p_aout->fifo[i_fifo].date );
1298                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1299                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1300                         continue;
1301                     }
1302
1303                     l_units = p_aout->l_units;
1304                     l_buffer = 0;
1305                     while ( l_units > 0 )
1306                     {
1307                         if ( !p_aout->fifo[i_fifo].b_next_frame )
1308                         {
1309                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
1310                             {
1311                                 break;
1312                             }
1313                         }
1314
1315                         if ( p_aout->fifo[i_fifo].l_units > l_units )
1316                         {
1317                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1318                             while ( l_buffer < l_buffer_limit )
1319                             {
1320                                 p_aout->s32_buffer[l_buffer++] +=
1321                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1322                                 p_aout->s32_buffer[l_buffer++] +=
1323                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1324
1325                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1326                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1327                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1328                                 {
1329                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1330                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1331                                 }
1332                             }
1333                             p_aout->fifo[i_fifo].l_units -= l_units;
1334                             break;
1335                         }
1336                         else
1337                         {
1338                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
1339                             /* p_aout->b_stereo == 1 */
1340                             while ( l_buffer < l_buffer_limit )
1341                             {
1342                                 p_aout->s32_buffer[l_buffer++] +=
1343                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1344                                 p_aout->s32_buffer[l_buffer++] +=
1345                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1346
1347                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1348                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1349                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1350                                 {
1351                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1352                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1353                                 }
1354                             }
1355                             l_units -= p_aout->fifo[i_fifo].l_units;
1356
1357                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1358                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1359                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1360                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1361
1362                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1363                             p_aout->fifo[i_fifo].l_next_frame += 1;
1364                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1365                             p_aout->fifo[i_fifo].b_next_frame = 0;
1366                         }
1367                     }
1368                     break;
1369
1370             default:
1371                     intf_DbgMsg("aout debug: unknown fifo type (%i)", p_aout->fifo[i_fifo].i_type);
1372                     break;
1373             }
1374         }
1375         vlc_mutex_unlock( &p_aout->fifos_lock );
1376
1377         l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1378
1379         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
1380         {
1381             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( ( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS ) * p_aout->vol / 256 ) ;
1382             p_aout->s32_buffer[l_buffer] = 0;
1383         }
1384
1385         l_bytes = p_aout->pf_getbufinfo( p_aout, l_buffer_limit );
1386         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
1387         p_aout->pf_play( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
1388         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
1389         {
1390             msleep( p_aout->l_msleep );
1391         }
1392     }
1393
1394     vlc_mutex_lock( &p_aout->fifos_lock );
1395     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
1396     {
1397         switch ( p_aout->fifo[i_fifo].i_type )
1398         {
1399             case AOUT_EMPTY_FIFO:
1400                 break;
1401
1402             case AOUT_INTF_MONO_FIFO:
1403             case AOUT_INTF_STEREO_FIFO:
1404                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
1405                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1406                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1407                 break;
1408
1409             case AOUT_ADEC_MONO_FIFO:
1410             case AOUT_ADEC_STEREO_FIFO:
1411                 free( p_aout->fifo[i_fifo].buffer );
1412                 free( p_aout->fifo[i_fifo].date );
1413                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1414                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed", &p_aout->fifo[i_fifo]);
1415                 break;
1416
1417             default:
1418                 break;
1419         }
1420     }
1421     vlc_mutex_unlock( &p_aout->fifos_lock );
1422 }
1423
1424 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
1425 {
1426 }
1427
1428 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
1429 {
1430 }