]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
D�but du portage BeOS. Beaucoup de fuchiers ont �t� modifi� car il a fallu
[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:
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 GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public
19  * License along with this program; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  *****************************************************************************/
23
24 /* TODO:
25  *
26  * - Passer un certain nombre de "fonctions" (genre add_samples) en macro ou
27  *   inline
28  * - Faire les optimisations dans les fonctions threads :
29  *   = Stocker les "petits calculs" dans des variables au lieu de les refaire
30  *     à chaque boucle
31  *   = Utiliser des tables pour les gros calculs
32  * - Faire une structure différente pour intf/adec fifo
33  *
34  */
35
36 /*****************************************************************************
37  * Preamble
38  *****************************************************************************/
39 #include <unistd.h>                                              /* getpid() */
40
41 #include <stdio.h>                                           /* "intf_msg.h" */
42 #include <stdlib.h>                            /* calloc(), malloc(), free() */
43
44 #include "threads.h"
45 #include "common.h"
46 #include "config.h"
47 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
48 #include "plugins.h"
49
50 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
51
52 #include "audio_output.h"
53 #include "main.h"
54
55 /*****************************************************************************
56  * Local prototypes
57  *****************************************************************************/
58
59 static int aout_SpawnThread( aout_thread_t * p_aout );
60
61 /* Creating as much aout_Thread functions as configurations is one solution,
62  * examining the different cases in the Thread loop of an unique function is
63  * another. I chose the first solution. */
64 void aout_Thread_S8_Mono        ( aout_thread_t * p_aout );
65 void aout_Thread_U8_Mono        ( aout_thread_t * p_aout );
66 void aout_Thread_S16_Mono       ( aout_thread_t * p_aout );
67 void aout_Thread_U16_Mono       ( aout_thread_t * p_aout );
68 void aout_Thread_S8_Stereo      ( aout_thread_t * p_aout );
69 void aout_Thread_U8_Stereo      ( aout_thread_t * p_aout );
70 void aout_Thread_S16_Stereo     ( aout_thread_t * p_aout );
71 void aout_Thread_U16_Stereo     ( aout_thread_t * p_aout );
72
73 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
74 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date );
75
76 /*****************************************************************************
77  * aout_CreateThread: initialize audio thread
78  *****************************************************************************/
79 aout_thread_t *aout_CreateThread( int *pi_status )
80 {
81     aout_thread_t * p_aout;                             /* thread descriptor */
82     char * psz_method;
83 #if 0
84     int             i_status;                                 /* thread status */
85 #endif
86
87     /* Allocate descriptor */
88     p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
89     if( p_aout == NULL )
90     {
91         return( NULL );
92     }
93
94     /* Request an interface plugin */
95     psz_method = main_GetPszVariable( AOUT_METHOD_VAR, AOUT_DEFAULT_METHOD );
96
97     if( RequestPlugin( &p_aout->aout_plugin, "aout", psz_method ) )
98     {
99         intf_ErrMsg( "error: could not open audio plugin aout_%s.so\n", psz_method );
100         free( p_aout );
101         return( NULL );
102     }
103
104     /* Get plugins */
105     p_aout->p_sys_open =         GetPluginFunction( p_aout->aout_plugin, "aout_SysOpen" );
106     p_aout->p_sys_reset =        GetPluginFunction( p_aout->aout_plugin, "aout_SysReset" );
107     p_aout->p_sys_setformat =    GetPluginFunction( p_aout->aout_plugin, "aout_SysSetFormat" );
108     p_aout->p_sys_setchannels =  GetPluginFunction( p_aout->aout_plugin, "aout_SysSetChannels" );
109     p_aout->p_sys_setrate =      GetPluginFunction( p_aout->aout_plugin, "aout_SysSetRate" );
110     p_aout->p_sys_getbufinfo =   GetPluginFunction( p_aout->aout_plugin, "aout_SysGetBufInfo" );
111     p_aout->p_sys_playsamples =  GetPluginFunction( p_aout->aout_plugin, "aout_SysPlaySamples" );
112     p_aout->p_sys_close =        GetPluginFunction( p_aout->aout_plugin, "aout_SysClose" );
113
114     /*
115      * Initialize audio device
116      */
117     if ( p_aout->p_sys_open( p_aout ) )
118     {
119         TrashPlugin( p_aout->aout_plugin );
120         free( p_aout );
121         return( NULL );
122     }
123
124     p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0; /* FIXME: only works
125                                                    for i_channels == 1 or 2 ??*/
126
127     if ( p_aout->p_sys_reset( p_aout ) )
128     {
129         p_aout->p_sys_close( p_aout );
130         TrashPlugin( p_aout->aout_plugin );
131         free( p_aout );
132         return( NULL );
133     }
134     if ( p_aout->p_sys_setformat( p_aout ) )
135     {
136         p_aout->p_sys_close( p_aout );
137         TrashPlugin( p_aout->aout_plugin );
138         free( p_aout );
139         return( NULL );
140     }
141     if ( p_aout->p_sys_setchannels( p_aout ) )
142     {
143         p_aout->p_sys_close( p_aout );
144         TrashPlugin( p_aout->aout_plugin );
145         free( p_aout );
146         return( NULL );
147     }
148     if ( p_aout->p_sys_setrate( p_aout ) )
149     {
150         p_aout->p_sys_close( p_aout );
151         TrashPlugin( p_aout->aout_plugin );
152         free( p_aout );
153         return( NULL );
154     }
155
156     /* FIXME: maybe it would be cleaner to change SpawnThread prototype
157      * see vout to handle status correctly ?? however, it is not critical since
158      * this thread is only called in main and all calls are blocking */
159     if( aout_SpawnThread( p_aout ) )
160     {
161         p_aout->p_sys_close( p_aout );
162         TrashPlugin( p_aout->aout_plugin );
163         free( p_aout );
164         return( NULL );
165     }
166
167     return( p_aout );
168 }
169
170 /*****************************************************************************
171  * aout_SpawnThread
172  *****************************************************************************/
173 static int aout_SpawnThread( aout_thread_t * p_aout )
174 {
175     int             i_fifo;
176     long            l_bytes;
177     void *          aout_thread = NULL;
178
179     intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);
180
181     /* We want the audio output thread to live */
182     p_aout->b_die = 0;
183
184     /* Initialize the fifos lock */
185     vlc_mutex_init( &p_aout->fifos_lock );
186     /* Initialize audio fifos : set all fifos as empty and initialize locks */
187     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
188     {
189         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
190         vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
191         vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
192     }
193
194     /* Compute the size (in audio units) of the audio output buffer. Although
195      * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
196      * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
197     p_aout->l_units = (long)( ((s64)p_aout->l_rate * AOUT_BUFFER_DURATION) / 1000000 );
198     p_aout->l_msleep = (long)( ((s64)p_aout->l_units * 1000000) / (s64)p_aout->l_rate );
199
200     /* Make aout_thread point to the right thread function, and compute the
201      * byte size of the audio output buffer */
202     switch ( p_aout->i_channels )
203     {
204         /* Audio output is mono */
205         case 1:
206             switch ( p_aout->i_format )
207             {
208                 case AOUT_FMT_U8:
209                     l_bytes = 1 * sizeof(u8) * p_aout->l_units;
210                     aout_thread = (void *)aout_Thread_U8_Mono;
211                     break;
212
213                 case AOUT_FMT_S8:
214                     l_bytes = 1 * sizeof(s8) * p_aout->l_units;
215                     aout_thread = (void *)aout_Thread_S8_Mono;
216                     break;
217
218                 case AOUT_FMT_U16_LE:
219                 case AOUT_FMT_U16_BE:
220                     l_bytes = 1 * sizeof(u16) * p_aout->l_units;
221                     aout_thread = (void *)aout_Thread_U16_Mono;
222                     break;
223
224                 case AOUT_FMT_S16_LE:
225                 case AOUT_FMT_S16_BE:
226                     l_bytes = 1 * sizeof(s16) * p_aout->l_units;
227                     aout_thread = (void *)aout_Thread_S16_Mono;
228                     break;
229
230                 default:
231                     intf_ErrMsg( "aout error: unknown audio output format (%i)\n",
232                                  p_aout->i_format );
233                     return( -1 );
234             }
235             break;
236
237         /* Audio output is stereo */
238         case 2:
239             switch ( p_aout->i_format )
240             {
241                 case AOUT_FMT_U8:
242                     l_bytes = 2 * sizeof(u8) * p_aout->l_units;
243                     aout_thread = (void *)aout_Thread_U8_Stereo;
244                     break;
245
246                 case AOUT_FMT_S8:
247                     l_bytes = 2 * sizeof(s8) * p_aout->l_units;
248                     aout_thread = (void *)aout_Thread_S8_Stereo;
249                     break;
250
251                 case AOUT_FMT_U16_LE:
252                 case AOUT_FMT_U16_BE:
253                     l_bytes = 2 * sizeof(u16) * p_aout->l_units;
254                     aout_thread = (void *)aout_Thread_U16_Stereo;
255                     break;
256
257                 case AOUT_FMT_S16_LE:
258                 case AOUT_FMT_S16_BE:
259                     l_bytes = 2 * sizeof(s16) * p_aout->l_units;
260                     aout_thread = (void *)aout_Thread_S16_Stereo;
261                     break;
262
263                 default:
264                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
265                         p_aout->i_format);
266                     return( -1 );
267             }
268             break;
269
270         default:
271             intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
272                 p_aout->i_channels );
273             return( -1 );
274     }
275
276     /* Allocate the memory needed by the audio output buffers, and set to zero
277      * the s32 buffer's memory */
278     if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
279     {
280         intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
281         return( -1 );
282     }
283     if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << ( p_aout->b_stereo))) == NULL )
284     {
285         intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
286         free( p_aout->buffer );
287         return( -1 );
288     }
289
290     /* Before launching the thread, we try to predict the date of the first
291      * audio unit in the first output buffer */
292     p_aout->date = mdate() - 1000000;
293
294     /* Launch the thread */
295     if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
296     {
297         intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
298         free( p_aout->buffer );
299         free( p_aout->s32_buffer );
300         return( -1 );
301     }
302
303     intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
304     return( 0 );
305 }
306
307 /*****************************************************************************
308  * aout_DestroyThread
309  *****************************************************************************/
310 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
311 {
312     /* FIXME: pi_status is not handled correctly: check vout how to do!?? */
313
314     intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
315
316     /* Ask thread to kill itself and wait until it's done */
317     p_aout->b_die = 1;
318     vlc_thread_join( p_aout->thread_id ); /* only if pi_status is NULL */
319
320     /* Free the allocated memory */
321     free( p_aout->buffer );
322     free( p_aout->s32_buffer );
323
324     /* Free the structure */
325     p_aout->p_sys_close( p_aout );
326     intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->psz_device);
327
328     /* Close plugin */
329     TrashPlugin( p_aout->aout_plugin );
330
331     /* Free structure */
332     free( p_aout );
333 }
334
335 /*****************************************************************************
336  * aout_CreateFifo
337  *****************************************************************************/
338 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
339 {
340     int i_fifo;
341
342     /* Take the fifos lock */
343     vlc_mutex_lock( &p_aout->fifos_lock );
344
345     /* Looking for a free fifo structure */
346     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
347     {
348         if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
349         {
350             break;
351         }
352     }
353     if ( i_fifo == AOUT_MAX_FIFOS )
354     {
355         intf_ErrMsg("aout error: no empty fifo available\n");
356         vlc_mutex_unlock( &p_aout->fifos_lock );
357         return( NULL );
358     }
359
360     /* Initialize the new fifo structure */
361     switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
362     {
363         case AOUT_INTF_MONO_FIFO:
364         case AOUT_INTF_STEREO_FIFO:
365             p_aout->fifo[i_fifo].b_die = 0;
366
367             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
368             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
369             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
370
371             p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
372
373             p_aout->fifo[i_fifo].l_unit = 0;
374             InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->l_rate );
375             p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
376             break;
377
378         case AOUT_ADEC_MONO_FIFO:
379         case AOUT_ADEC_STEREO_FIFO:
380             p_aout->fifo[i_fifo].b_die = 0;
381
382             p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
383             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
384             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
385
386             p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
387             /* Allocate the memory needed to store the audio frames. As the
388              * fifo is a rotative fifo, we must be able to find out whether the
389              * fifo is full or empty, that's why we must in fact allocate memory
390              * for (AOUT_FIFO_SIZE+1) audio frames. */
391             if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
392             {
393                 intf_ErrMsg("aout error: not enough memory to create the frames buffer\n");
394                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
395                 vlc_mutex_unlock( &p_aout->fifos_lock );
396                 return( NULL );
397             }
398
399             /* Allocate the memory needed to store the dates of the frames */
400             if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
401             {
402                 intf_ErrMsg("aout error: not enough memory to create the dates buffer\n");
403                 free( p_aout->fifo[i_fifo].buffer );
404                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
405                 vlc_mutex_unlock( &p_aout->fifos_lock );
406                 return( NULL );
407             }
408
409             /* Set the fifo's buffer as empty (the first frame that is to be
410              * played is also the first frame that is not to be played) */
411             p_aout->fifo[i_fifo].l_start_frame = 0;
412             /* p_aout->fifo[i_fifo].l_next_frame = 0; */
413             p_aout->fifo[i_fifo].l_end_frame = 0;
414
415             /* Waiting for the audio decoder to compute enough frames to work
416              * out the fifo's current rate (as soon as the decoder has decoded
417              * enough frames, the members of the fifo structure that are not
418              * initialized now will be calculated) */
419             p_aout->fifo[i_fifo].b_start_frame = 0;
420             p_aout->fifo[i_fifo].b_next_frame = 0;
421             break;
422
423         default:
424             intf_ErrMsg("aout error: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
425             p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
426             vlc_mutex_unlock( &p_aout->fifos_lock );
427             return( NULL );
428     }
429
430     /* Release the fifos lock */
431     vlc_mutex_unlock( &p_aout->fifos_lock );
432
433     /* Return the pointer to the fifo structure */
434     intf_DbgMsg("aout debug: audio output fifo (%p) allocated\n", &p_aout->fifo[i_fifo]);
435     return( &p_aout->fifo[i_fifo] );
436 }
437
438 /*****************************************************************************
439  * aout_DestroyFifo
440  *****************************************************************************/
441 void aout_DestroyFifo( aout_fifo_t * p_fifo )
442 {
443     intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)\n", p_fifo);
444     p_fifo->b_die = 1;
445 }
446
447 /* Here are the local macros */
448
449 #define UPDATE_INCREMENT( increment, integer ) \
450     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
451     { \
452         (integer) += (increment).l_euclidean_integer + 1; \
453         (increment).l_remainder -= (increment).l_euclidean_denominator; \
454     } \
455     else \
456     { \
457         (integer) += (increment).l_euclidean_integer; \
458     }
459
460 /* Following functions are local */
461
462 /*****************************************************************************
463  * InitializeIncrement
464  *****************************************************************************/
465 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
466 {
467     p_increment->l_remainder = -l_denominator;
468
469     p_increment->l_euclidean_integer = 0;
470     while ( l_numerator >= l_denominator )
471     {
472         p_increment->l_euclidean_integer++;
473         l_numerator -= l_denominator;
474     }
475
476     p_increment->l_euclidean_remainder = l_numerator;
477
478     p_increment->l_euclidean_denominator = l_denominator;
479 }
480
481 /*****************************************************************************
482  * NextFrame
483  *****************************************************************************/
484 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date )
485 {
486     long l_units, l_rate;
487
488     /* We take the lock */
489     vlc_mutex_lock( &p_fifo->data_lock );
490
491     /* Are we looking for a dated start frame ? */
492     if ( !p_fifo->b_start_frame )
493     {
494         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
495         {
496             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
497             {
498                 p_fifo->b_start_frame = 1;
499                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
500                 p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
501                 break;
502             }
503             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
504         }
505
506         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
507         {
508             vlc_mutex_unlock( &p_fifo->data_lock );
509             return( -1 );
510         }
511     }
512
513     /* We are looking for the next dated frame */
514     /* FIXME : is the output fifo full ?? */
515     while ( !p_fifo->b_next_frame )
516     {
517         while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
518         {
519             if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
520             {
521                 p_fifo->b_next_frame = 1;
522                 break;
523             }
524             p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
525         }
526
527         while ( p_fifo->l_next_frame == p_fifo->l_end_frame )
528         {
529             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
530             if ( p_fifo->b_die )
531             {
532                 vlc_mutex_unlock( &p_fifo->data_lock );
533                 return( -1 );
534             }
535         }
536     }
537
538     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
539
540     l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
541 //    fprintf( stderr, "aout debug: %lli (%li);\n", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
542
543     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->l_rate );
544
545     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
546         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo)))))
547         * p_aout->l_rate) / l_rate) + 1;
548
549     /* We release the lock before leaving */
550     vlc_mutex_unlock( &p_fifo->data_lock );
551     return( 0 );
552 }
553
554 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
555 {
556 }
557
558 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
559 {
560 }
561
562 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
563 {
564 }
565
566 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
567 {
568     int i_fifo;
569     long l_buffer, l_buffer_limit;
570     long l_units, l_bytes;
571
572     intf_DbgMsg("adec debug: ********aout_Thread_U8_Stereo********\n");
573     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
574
575     /* As the s32_buffer was created with calloc(), we don't have to set this
576      * memory to zero and we can immediately jump into the thread's loop */
577     while ( !p_aout->b_die )
578     {
579         vlc_mutex_lock( &p_aout->fifos_lock );
580         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
581         {
582             switch ( p_aout->fifo[i_fifo].i_type )
583             {
584                 case AOUT_EMPTY_FIFO:
585                     break;
586
587                 case AOUT_INTF_MONO_FIFO:
588                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
589                     {
590                         l_buffer = 0;
591                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
592                         {
593                             p_aout->s32_buffer[l_buffer++] +=
594                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
595                             p_aout->s32_buffer[l_buffer++] +=
596                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
597                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
598                         }
599                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
600                     }
601                     else
602                     {
603                         l_buffer = 0;
604                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
605                         {
606                             p_aout->s32_buffer[l_buffer++] +=
607                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
608                             p_aout->s32_buffer[l_buffer++] +=
609                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
610                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
611                         }
612                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
613                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
614                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
615                     }
616                     break;
617
618                 case AOUT_INTF_STEREO_FIFO:
619                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
620                     {
621                         l_buffer = 0;
622                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
623                         {
624                             p_aout->s32_buffer[l_buffer++] +=
625                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
626                             p_aout->s32_buffer[l_buffer++] +=
627                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
628                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
629                         }
630                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
631                     }
632                     else
633                     {
634                         l_buffer = 0;
635                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
636                         {
637                             p_aout->s32_buffer[l_buffer++] +=
638                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
639                             p_aout->s32_buffer[l_buffer++] +=
640                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
641                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
642                         }
643                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
644                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
645                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
646                     }
647                     break;
648
649                 case AOUT_ADEC_MONO_FIFO:
650                     if ( p_aout->fifo[i_fifo].b_die )
651                     {
652                         free( p_aout->fifo[i_fifo].buffer );
653                         free( p_aout->fifo[i_fifo].date );
654                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
655                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
656                         continue;
657                     }
658
659                     l_units = p_aout->l_units;
660                     l_buffer = 0;
661                     while ( l_units > 0 )
662                     {
663                         if ( !p_aout->fifo[i_fifo].b_next_frame )
664                         {
665                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
666                             {
667                                 break;
668                             }
669                         }
670
671                         if ( p_aout->fifo[i_fifo].l_units > l_units )
672                         {
673                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
674                             while ( l_buffer < l_buffer_limit )
675                             {
676                                 p_aout->s32_buffer[l_buffer++] +=
677                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
678                                 p_aout->s32_buffer[l_buffer++] +=
679                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
680
681                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
682                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
683                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
684                                 {
685                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
686                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
687                                 }
688                             }
689                             p_aout->fifo[i_fifo].l_units -= l_units;
690                             break;
691                         }
692                         else
693                         {
694                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
695                             /* p_aout->b_stereo == 1 */
696                             while ( l_buffer < l_buffer_limit )
697                             {
698                                 p_aout->s32_buffer[l_buffer++] +=
699                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
700                                 p_aout->s32_buffer[l_buffer++] +=
701                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
702
703                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
704                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
705                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
706                                 {
707                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
708                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
709                                 }
710                             }
711                             l_units -= p_aout->fifo[i_fifo].l_units;
712
713                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
714                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
715                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
716                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
717
718                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
719                             p_aout->fifo[i_fifo].l_next_frame += 1;
720                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
721                             p_aout->fifo[i_fifo].b_next_frame = 0;
722                         }
723                     }
724                     break;
725
726                 case AOUT_ADEC_STEREO_FIFO:
727                     if ( p_aout->fifo[i_fifo].b_die )
728                     {
729                         free( p_aout->fifo[i_fifo].buffer );
730                         free( p_aout->fifo[i_fifo].date );
731                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
732                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
733                         continue;
734                     }
735
736                     l_units = p_aout->l_units;
737                     l_buffer = 0;
738                     while ( l_units > 0 )
739                     {
740                         if ( !p_aout->fifo[i_fifo].b_next_frame )
741                         {
742                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
743                             {
744                                 break;
745                             }
746                         }
747
748                         if ( p_aout->fifo[i_fifo].l_units > l_units )
749                         {
750                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
751                             while ( l_buffer < l_buffer_limit )
752                             {
753                                 p_aout->s32_buffer[l_buffer++] +=
754                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
755                                 p_aout->s32_buffer[l_buffer++] +=
756                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
757
758                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
759                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
760                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
761                                 {
762                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
763                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
764                                 }
765                             }
766                             p_aout->fifo[i_fifo].l_units -= l_units;
767                             break;
768                         }
769                         else
770                         {
771                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
772                             /* p_aout->b_stereo == 1 */
773                             while ( l_buffer < l_buffer_limit )
774                             {
775                                 p_aout->s32_buffer[l_buffer++] +=
776                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
777                                 p_aout->s32_buffer[l_buffer++] +=
778                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
779
780                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
781                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
782                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
783                                 {
784                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
785                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
786                                 }
787                             }
788                             l_units -= p_aout->fifo[i_fifo].l_units;
789
790                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
791                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
792                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
793                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
794
795                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
796                             p_aout->fifo[i_fifo].l_next_frame += 1;
797                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
798                             p_aout->fifo[i_fifo].b_next_frame = 0;
799                         }
800                     }
801                     break;
802
803             default:
804                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
805                     break;
806             }
807         }
808         vlc_mutex_unlock( &p_aout->fifos_lock );
809
810         l_buffer_limit = p_aout->l_units  << 1 ; /* p_aout->b_stereo == 1 */
811
812         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
813         {
814             ((u8 *)p_aout->buffer)[l_buffer] = (u8)( (p_aout->s32_buffer[l_buffer] / 256) + 128 );
815             p_aout->s32_buffer[l_buffer] = 0;
816         }
817         l_bytes = p_aout->p_sys_getbufinfo( p_aout, l_buffer_limit );
818         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 2 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 2 */
819         p_aout->p_sys_playsamples( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
820         if ( l_bytes > (l_buffer_limit * sizeof(u8)) )
821         {
822             msleep( p_aout->l_msleep );
823         }
824     }
825
826     vlc_mutex_lock( &p_aout->fifos_lock );
827     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
828     {
829         switch ( p_aout->fifo[i_fifo].i_type )
830         {
831             case AOUT_EMPTY_FIFO:
832                 break;
833
834             case AOUT_INTF_MONO_FIFO:
835             case AOUT_INTF_STEREO_FIFO:
836                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
837                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
838                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
839                 break;
840
841             case AOUT_ADEC_MONO_FIFO:
842             case AOUT_ADEC_STEREO_FIFO:
843                 free( p_aout->fifo[i_fifo].buffer );
844                 free( p_aout->fifo[i_fifo].date );
845                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
846                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
847                 break;
848
849             default:
850                 break;
851         }
852     }
853     vlc_mutex_unlock( &p_aout->fifos_lock );
854
855 }
856
857 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
858 {
859 }
860
861 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
862 {
863     int i_fifo;
864     long l_buffer, l_buffer_limit;
865     long l_units, l_bytes;
866
867     intf_DbgMsg("adec debug: ********aout_Thread_S16_Stereo********\n");
868     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
869
870     /* As the s32_buffer was created with calloc(), we don't have to set this
871      * memory to zero and we can immediately jump into the thread's loop */
872     while ( !p_aout->b_die )
873     {
874         vlc_mutex_lock( &p_aout->fifos_lock );
875         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
876         {
877             switch ( p_aout->fifo[i_fifo].i_type )
878             {
879                 case AOUT_EMPTY_FIFO:
880                     break;
881
882                 case AOUT_INTF_MONO_FIFO:
883                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
884                     {
885                         l_buffer = 0;
886                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
887                         {
888                             p_aout->s32_buffer[l_buffer++] +=
889                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
890                             p_aout->s32_buffer[l_buffer++] +=
891                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
892                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
893                         }
894                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
895                     }
896                     else
897                     {
898                         l_buffer = 0;
899                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
900                         {
901                             p_aout->s32_buffer[l_buffer++] +=
902                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
903                             p_aout->s32_buffer[l_buffer++] +=
904                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
905                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
906                         }
907                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
908                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
909                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
910                     }
911                     break;
912
913                 case AOUT_INTF_STEREO_FIFO:
914                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
915                     {
916                         l_buffer = 0;
917                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
918                         {
919                             p_aout->s32_buffer[l_buffer++] +=
920                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
921                             p_aout->s32_buffer[l_buffer++] +=
922                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
923                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
924                         }
925                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
926                     }
927                     else
928                     {
929                         l_buffer = 0;
930                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
931                         {
932                             p_aout->s32_buffer[l_buffer++] +=
933                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
934                             p_aout->s32_buffer[l_buffer++] +=
935                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
936                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
937                         }
938                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
939                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
940                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
941                     }
942                     break;
943
944                 case AOUT_ADEC_MONO_FIFO:
945                     if ( p_aout->fifo[i_fifo].b_die )
946                     {
947                         free( p_aout->fifo[i_fifo].buffer );
948                         free( p_aout->fifo[i_fifo].date );
949                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
950                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
951                         continue;
952                     }
953
954                     l_units = p_aout->l_units;
955                     l_buffer = 0;
956                     while ( l_units > 0 )
957                     {
958                         if ( !p_aout->fifo[i_fifo].b_next_frame )
959                         {
960                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
961                             {
962                                 break;
963                             }
964                         }
965
966                         if ( p_aout->fifo[i_fifo].l_units > l_units )
967                         {
968                             l_buffer_limit = p_aout->l_units << 1; /* 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                             p_aout->fifo[i_fifo].l_units -= l_units;
985                             break;
986                         }
987                         else
988                         {
989                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
990                             /* p_aout->b_stereo == 1 */
991                             while ( l_buffer < l_buffer_limit )
992                             {
993                                 p_aout->s32_buffer[l_buffer++] +=
994                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
995                                 p_aout->s32_buffer[l_buffer++] +=
996                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
997
998                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
999                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1000                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
1001                                 {
1002                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
1003                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
1004                                 }
1005                             }
1006                             l_units -= p_aout->fifo[i_fifo].l_units;
1007
1008                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1009                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1010                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1011                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1012
1013                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1014                             p_aout->fifo[i_fifo].l_next_frame += 1;
1015                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1016                             p_aout->fifo[i_fifo].b_next_frame = 0;
1017                         }
1018                     }
1019                     break;
1020
1021                 case AOUT_ADEC_STEREO_FIFO:
1022                     if ( p_aout->fifo[i_fifo].b_die )
1023                     {
1024                         free( p_aout->fifo[i_fifo].buffer );
1025                         free( p_aout->fifo[i_fifo].date );
1026                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1027                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
1028                         continue;
1029                     }
1030
1031                     l_units = p_aout->l_units;
1032                     l_buffer = 0;
1033                     while ( l_units > 0 )
1034                     {
1035                         if ( !p_aout->fifo[i_fifo].b_next_frame )
1036                         {
1037                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
1038                             {
1039                                 break;
1040                             }
1041                         }
1042
1043                         if ( p_aout->fifo[i_fifo].l_units > l_units )
1044                         {
1045                             l_buffer_limit = p_aout->l_units << 1; /* 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                             p_aout->fifo[i_fifo].l_units -= l_units;
1062                             break;
1063                         }
1064                         else
1065                         {
1066                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
1067                             /* p_aout->b_stereo == 1 */
1068                             while ( l_buffer < l_buffer_limit )
1069                             {
1070                                 p_aout->s32_buffer[l_buffer++] +=
1071                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
1072                                 p_aout->s32_buffer[l_buffer++] +=
1073                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
1074
1075                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
1076                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1077                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
1078                                 {
1079                                     p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
1080                                         ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
1081                                 }
1082                             }
1083                             l_units -= p_aout->fifo[i_fifo].l_units;
1084
1085                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
1086                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
1087                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
1088                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
1089
1090                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
1091                             p_aout->fifo[i_fifo].l_next_frame += 1;
1092                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
1093                             p_aout->fifo[i_fifo].b_next_frame = 0;
1094                         }
1095                     }
1096                     break;
1097
1098             default:
1099                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
1100                     break;
1101             }
1102         }
1103         vlc_mutex_unlock( &p_aout->fifos_lock );
1104
1105         l_buffer_limit = p_aout->l_units << 1; /* p_aout->b_stereo == 1 */
1106
1107         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
1108         {
1109             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
1110             p_aout->s32_buffer[l_buffer] = 0;
1111         }
1112
1113         l_bytes = p_aout->p_sys_getbufinfo( p_aout, l_buffer_limit );
1114         p_aout->date = -1000000 + mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(s16) << (p_aout->b_stereo) == 4 */
1115         p_aout->p_sys_playsamples( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
1116         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
1117         {
1118             msleep( p_aout->l_msleep );
1119         }
1120     }
1121
1122     vlc_mutex_lock( &p_aout->fifos_lock );
1123     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
1124     {
1125         switch ( p_aout->fifo[i_fifo].i_type )
1126         {
1127             case AOUT_EMPTY_FIFO:
1128                 break;
1129
1130             case AOUT_INTF_MONO_FIFO:
1131             case AOUT_INTF_STEREO_FIFO:
1132                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
1133                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1134                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
1135                 break;
1136
1137             case AOUT_ADEC_MONO_FIFO:
1138             case AOUT_ADEC_STEREO_FIFO:
1139                 free( p_aout->fifo[i_fifo].buffer );
1140                 free( p_aout->fifo[i_fifo].date );
1141                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
1142                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
1143                 break;
1144
1145             default:
1146                 break;
1147         }
1148     }
1149     vlc_mutex_unlock( &p_aout->fifos_lock );
1150 }
1151
1152 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
1153 {
1154 }
1155
1156 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
1157 {
1158 }