]> git.sesse.net Git - vlc/blob - src/audio_output/audio_output.c
o changement de nom des fonctions sp�cifiques BeOS
[vlc] / src / audio_output / audio_output.c
1 /*****************************************************************************
2  * audio_output.c : audio output thread
3  * (c)1999 VideoLAN
4  *****************************************************************************/
5
6 /* TODO:
7  *
8  * - Passer un certain nombre de "fonctions" (genre add_samples) en macro ou
9  *   inline
10  * - Faire les optimisations dans les fonctions threads :
11  *   = Stocker les "petits calculs" dans des variables au lieu de les refaire
12  *     à chaque boucle
13  *   = Utiliser des tables pour les gros calculs
14  * - Faire une structure différente pour intf/adec fifo
15  *
16  */
17
18 /*****************************************************************************
19  * Preamble
20  *****************************************************************************/
21 #include <unistd.h>
22
23 #include <sys/soundcard.h>
24 #include <stdio.h>                                           /* "intf_msg.h" */
25 #include <stdlib.h>                            /* calloc(), malloc(), free() */
26
27 #include "common.h"
28 #include "config.h"
29 #include "mtime.h"                             /* mtime_t, mdate(), msleep() */
30 #include "vlc_thread.h"
31
32 #include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
33
34 #include "audio_output.h"
35 #include "audio_sys.h"
36 #include "main.h"
37
38 /*****************************************************************************
39  * Local prototypes
40  *****************************************************************************/
41
42 static int aout_SpawnThread( aout_thread_t * p_aout );
43
44 /* Creating as much aout_Thread functions as configurations is one solution,
45  * examining the different cases in the Thread loop of an unique function is
46  * another. I chose the first solution. */
47 void aout_Thread_S8_Mono        ( aout_thread_t * p_aout );
48 void aout_Thread_U8_Mono        ( aout_thread_t * p_aout );
49 void aout_Thread_S16_Mono       ( aout_thread_t * p_aout );
50 void aout_Thread_U16_Mono       ( aout_thread_t * p_aout );
51 void aout_Thread_S8_Stereo      ( aout_thread_t * p_aout );
52 void aout_Thread_U8_Stereo      ( aout_thread_t * p_aout );
53 void aout_Thread_S16_Stereo     ( aout_thread_t * p_aout );
54 void aout_Thread_U16_Stereo     ( aout_thread_t * p_aout );
55
56 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
57 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date );
58
59 /*****************************************************************************
60  * aout_CreateThread: initialize audio thread
61  *****************************************************************************/
62 aout_thread_t *aout_CreateThread( int *pi_status )
63 {
64     aout_thread_t * p_aout;                             /* thread descriptor */
65     char * psz_method;
66 //    int             i_status;                                 /* thread status */
67
68     /* Allocate descriptor */
69     p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
70     if( p_aout == NULL )
71     {
72         return( NULL );
73     }
74
75     /* initialize method-dependent functions */
76     psz_method = main_GetPszVariable( AOUT_METHOD_VAR, AOUT_DEFAULT_METHOD );
77
78     if( !strcmp(psz_method, "dummy") )
79     {
80         p_aout->p_sys_open =           aout_DummySysOpen;
81         p_aout->p_sys_reset =          aout_DummySysReset;
82         p_aout->p_sys_setformat =      aout_DummySysSetFormat;
83         p_aout->p_sys_setchannels =    aout_DummySysSetChannels;
84         p_aout->p_sys_setrate =        aout_DummySysSetRate;
85         p_aout->p_sys_getbufinfo =     aout_DummySysGetBufInfo;
86         p_aout->p_sys_playsamples =    aout_DummySysPlaySamples;
87         p_aout->p_sys_close =          aout_DummySysClose;
88     }
89 #ifdef VIDEO_X11
90     else if( !strcmp(psz_method, "dsp") )
91     {
92         p_aout->p_sys_open =           aout_DspSysOpen;
93         p_aout->p_sys_reset =          aout_DspSysReset;
94         p_aout->p_sys_setformat =      aout_DspSysSetFormat;
95         p_aout->p_sys_setchannels =    aout_DspSysSetChannels;
96         p_aout->p_sys_setrate =        aout_DspSysSetRate;
97         p_aout->p_sys_getbufinfo =     aout_DspSysGetBufInfo;
98         p_aout->p_sys_playsamples =    aout_DspSysPlaySamples;
99         p_aout->p_sys_close =          aout_DspSysClose;
100     }
101 #endif
102     else
103     {
104         intf_ErrMsg( "error: requested audio output method not available\n" );
105         free( p_aout );
106         return( NULL );
107     }
108                 
109     //???? kludge to initialize some audio parameters - place this section somewhere
110     //???? else
111     p_aout->sys.i_format = AOUT_DEFAULT_FORMAT;
112     p_aout->sys.psz_device = main_GetPszVariable( AOUT_DSP_VAR, AOUT_DSP_DEFAULT );
113     p_aout->sys.b_stereo   = main_GetIntVariable( AOUT_STEREO_VAR, AOUT_STEREO_DEFAULT );
114     p_aout->sys.l_rate     = main_GetIntVariable( AOUT_RATE_VAR, AOUT_RATE_DEFAULT );
115     // ???? end of kludge
116
117     /*
118      * Initialize DSP
119      */
120     if ( p_aout->p_sys_open( &p_aout->sys ) )
121     {
122         free( p_aout );
123         return( NULL );
124     }
125     if ( p_aout->p_sys_reset( &p_aout->sys ) )
126     {
127         p_aout->p_sys_close( &p_aout->sys );
128         free( p_aout );
129         return( NULL );
130     }
131     if ( p_aout->p_sys_setformat( &p_aout->sys ) )
132     {
133         p_aout->p_sys_close( &p_aout->sys );
134         free( p_aout );
135         return( NULL );
136     }
137     if ( p_aout->p_sys_setchannels( &p_aout->sys ) )
138     {
139         p_aout->p_sys_close( &p_aout->sys );
140         free( p_aout );
141         return( NULL );
142     }
143     if ( p_aout->p_sys_setrate( &p_aout->sys ) )
144     {
145         p_aout->p_sys_close( &p_aout->sys );
146         free( p_aout );
147         return( NULL );
148     }
149     intf_DbgMsg("aout debug: audio device (%s) opened (format=%i, stereo=%i, rate=%li)\n",
150         p_aout->sys.psz_device,
151         p_aout->sys.i_format,
152         p_aout->sys.b_stereo, p_aout->sys.l_rate);
153
154     //?? maybe it would be cleaner to change SpawnThread prototype
155     //?? see vout to handle status correctly - however, it is not critical since
156     //?? this thread is only called in main and all calls are blocking
157     if( aout_SpawnThread( p_aout ) )
158     {
159         p_aout->p_sys_close( &p_aout->sys );
160         free( p_aout );
161         return( NULL );
162     }
163
164     return( p_aout );
165 }
166
167 /*****************************************************************************
168  * aout_SpawnThread
169  *****************************************************************************/
170 static int aout_SpawnThread( aout_thread_t * p_aout )
171 {
172     int             i_fifo;
173     long            l_bytes;
174     void *          aout_thread = NULL;
175
176     intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);
177
178     /* We want the audio output thread to live */
179     p_aout->b_die = 0;
180
181     /* Initialize the fifos lock */
182     vlc_mutex_init( &p_aout->fifos_lock );
183     /* Initialize audio fifos : set all fifos as empty and initialize locks */
184     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
185     {
186         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
187         vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
188         vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
189     }
190
191     /* Compute the size (in audio units) of the audio output buffer. Although
192      * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
193      * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
194     p_aout->l_units = (long)( ((s64)p_aout->sys.l_rate * AOUT_BUFFER_DURATION) / 1000000 );
195     p_aout->l_msleep = (long)( ((s64)p_aout->l_units * 1000000) / (s64)p_aout->sys.l_rate );
196
197     /* Make aout_thread point to the right thread function, and compute the
198      * byte size of the audio output buffer */
199     switch ( p_aout->sys.b_stereo )
200     {
201         /* Audio output is mono */
202         case 0:
203             switch ( p_aout->sys.i_format )
204             {
205                 case AFMT_U8:
206                     l_bytes = 1 * sizeof(u8) * p_aout->l_units;
207                     aout_thread = (void *)aout_Thread_U8_Mono;
208                     break;
209
210                 case AFMT_S8:
211                     l_bytes = 1 * sizeof(s8) * p_aout->l_units;
212                     aout_thread = (void *)aout_Thread_S8_Mono;
213                     break;
214
215                 case AFMT_U16_LE:
216                 case AFMT_U16_BE:
217                     l_bytes = 1 * sizeof(u16) * p_aout->l_units;
218                     aout_thread = (void *)aout_Thread_U16_Mono;
219                     break;
220
221                 case AFMT_S16_LE:
222                 case AFMT_S16_BE:
223                     l_bytes = 1 * sizeof(s16) * p_aout->l_units;
224                     aout_thread = (void *)aout_Thread_S16_Mono;
225                     break;
226
227                 default:
228                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
229                         p_aout->sys.i_format);
230                     return( -1 );
231             }
232             break;
233
234         /* Audio output is stereo */
235         case 1:
236             switch ( p_aout->sys.i_format )
237             {
238                 case AFMT_U8:
239                     l_bytes = 2 * sizeof(u8) * p_aout->l_units;
240                     aout_thread = (void *)aout_Thread_U8_Stereo;
241                     break;
242
243                 case AFMT_S8:
244                     l_bytes = 2 * sizeof(s8) * p_aout->l_units;
245                     aout_thread = (void *)aout_Thread_S8_Stereo;
246                     break;
247
248                 case AFMT_U16_LE:
249                 case AFMT_U16_BE:
250                     l_bytes = 2 * sizeof(u16) * p_aout->l_units;
251                     aout_thread = (void *)aout_Thread_U16_Stereo;
252                     break;
253
254                 case AFMT_S16_LE:
255                 case AFMT_S16_BE:
256                     l_bytes = 2 * sizeof(s16) * p_aout->l_units;
257                     aout_thread = (void *)aout_Thread_S16_Stereo;
258                     break;
259
260                 default:
261                     intf_ErrMsg("aout error: unknown audio output format (%i)\n",
262                         p_aout->sys.i_format);
263                     return( -1 );
264             }
265             break;
266
267         default:
268             intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
269                 p_aout->sys.b_stereo + 1);
270             return( -1 );
271     }
272
273     /* Allocate the memory needed by the audio output buffers, and set to zero
274      * the s32 buffer's memory */
275     if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
276     {
277         intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
278         return( -1 );
279     }
280     if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << p_aout->sys.b_stereo)) == NULL )
281     {
282         intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
283         free( p_aout->buffer );
284         return( -1 );
285     }
286
287     /* Before launching the thread, we try to predict the date of the first
288      * audio unit in the first output buffer */
289     p_aout->date = mdate();
290
291     /* Launch the thread */
292     if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
293     {
294         intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
295         free( p_aout->buffer );
296         free( p_aout->s32_buffer );
297         return( -1 );
298     }
299
300     intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
301     return( 0 );
302 }
303
304 /*****************************************************************************
305  * aout_DestroyThread
306  *****************************************************************************/
307 void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
308 {
309     //???? pi_status is not handled correctly: check vout how to do!
310
311     intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);
312
313     /* Ask thread to kill itself and wait until it's done */
314     p_aout->b_die = 1;
315     vlc_thread_join( p_aout->thread_id ); // only if pi_status is NULL
316
317     /* Free the allocated memory */
318     free( p_aout->buffer );
319     free( p_aout->s32_buffer );
320
321     /* Free the structure */
322     p_aout->p_sys_close( &p_aout->sys );
323     intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->sys.psz_device);
324     free( p_aout );
325 }
326
327 /*****************************************************************************
328  * aout_CreateFifo
329  *****************************************************************************/
330 aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
331 {
332     int i_fifo;
333
334     /* Take the fifos lock */
335     vlc_mutex_lock( &p_aout->fifos_lock );
336
337     /* Looking for a free fifo structure */
338     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
339     {
340         if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
341         {
342             break;
343         }
344     }
345     if ( i_fifo == AOUT_MAX_FIFOS )
346     {
347         intf_ErrMsg("aout error: no empty fifo available\n");
348         vlc_mutex_unlock( &p_aout->fifos_lock );
349         return( NULL );
350     }
351
352     /* Initialize the new fifo structure */
353     switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
354     {
355         case AOUT_INTF_MONO_FIFO:
356         case AOUT_INTF_STEREO_FIFO:
357             p_aout->fifo[i_fifo].b_die = 0;
358
359             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
360             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
361
362             p_aout->fifo[i_fifo].buffer = p_fifo->buffer;
363
364             p_aout->fifo[i_fifo].l_unit = 0;
365             InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->sys.l_rate );
366             p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
367             break;
368
369         case AOUT_ADEC_MONO_FIFO:
370         case AOUT_ADEC_STEREO_FIFO:
371             p_aout->fifo[i_fifo].b_die = 0;
372
373             p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
374             p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
375
376             p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
377             /* Allocate the memory needed to store the audio frames. As the
378              * fifo is a rotative fifo, we must be able to find out whether the
379              * fifo is full or empty, that's why we must in fact allocate memory
380              * for (AOUT_FIFO_SIZE+1) audio frames. */
381             if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
382             {
383                 intf_ErrMsg("aout error: not enough memory to create the frames buffer\n");
384                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
385                 vlc_mutex_unlock( &p_aout->fifos_lock );
386                 return( NULL );
387             }
388
389             /* Allocate the memory needed to store the dates of the frames */
390             if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
391             {
392                 intf_ErrMsg("aout error: not enough memory to create the dates buffer\n");
393                 free( p_aout->fifo[i_fifo].buffer );
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             /* Set the fifo's buffer as empty (the first frame that is to be
400              * played is also the first frame that is not to be played) */
401             p_aout->fifo[i_fifo].l_start_frame = 0;
402             /* p_aout->fifo[i_fifo].l_next_frame = 0; */
403             p_aout->fifo[i_fifo].l_end_frame = 0;
404
405             /* Waiting for the audio decoder to compute enough frames to work
406              * out the fifo's current rate (as soon as the decoder has decoded
407              * enough frames, the members of the fifo structure that are not
408              * initialized now will be calculated) */
409             p_aout->fifo[i_fifo].b_start_frame = 0;
410             p_aout->fifo[i_fifo].b_next_frame = 0;
411             break;
412
413         default:
414             intf_ErrMsg("aout error: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
415             p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
416             vlc_mutex_unlock( &p_aout->fifos_lock );
417             return( NULL );
418     }
419
420     /* Release the fifos lock */
421     vlc_mutex_unlock( &p_aout->fifos_lock );
422
423     /* Return the pointer to the fifo structure */
424     intf_DbgMsg("aout debug: audio output fifo (%p) allocated\n", &p_aout->fifo[i_fifo]);
425     return( &p_aout->fifo[i_fifo] );
426 }
427
428 /*****************************************************************************
429  * aout_DestroyFifo
430  *****************************************************************************/
431 void aout_DestroyFifo( aout_fifo_t * p_fifo )
432 {
433     intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)\n", p_fifo);
434     p_fifo->b_die = 1;
435 }
436
437 /* Here are the local macros */
438
439 #define UPDATE_INCREMENT( increment, integer ) \
440     if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
441     { \
442         (integer) += (increment).l_euclidean_integer + 1; \
443         (increment).l_remainder -= (increment).l_euclidean_denominator; \
444     } \
445     else \
446     { \
447         (integer) += (increment).l_euclidean_integer; \
448     }
449
450 /* Following functions are local */
451
452 /*****************************************************************************
453  * InitializeIncrement
454  *****************************************************************************/
455 static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
456 {
457     p_increment->l_remainder = -l_denominator;
458
459     p_increment->l_euclidean_integer = 0;
460     while ( l_numerator >= l_denominator )
461     {
462         p_increment->l_euclidean_integer++;
463         l_numerator -= l_denominator;
464     }
465
466     p_increment->l_euclidean_remainder = l_numerator;
467
468     p_increment->l_euclidean_denominator = l_denominator;
469 }
470
471 /*****************************************************************************
472  * NextFrame
473  *****************************************************************************/
474 static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date )
475 {
476     long l_units, l_rate;
477
478     /* We take the lock */
479     vlc_mutex_lock( &p_fifo->data_lock );
480
481     /* Are we looking for a dated start frame ? */
482     if ( !p_fifo->b_start_frame )
483     {
484         while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
485         {
486             if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
487             {
488                 p_fifo->b_start_frame = 1;
489                 p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
490                 p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo);
491                 break;
492             }
493             p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
494         }
495
496         if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
497         {
498             vlc_mutex_unlock( &p_fifo->data_lock );
499             return( -1 );
500         }
501     }
502
503     /* We are looking for the next dated frame */
504     /* FIXME : is the output fifo full ? */
505     while ( !p_fifo->b_next_frame )
506     {
507         while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
508         {
509             if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
510             {
511                 p_fifo->b_next_frame = 1;
512                 break;
513             }
514             p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
515         }
516
517         while ( p_fifo->l_next_frame == p_fifo->l_end_frame )
518         {
519             vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
520             if ( p_fifo->b_die )
521             {
522                 vlc_mutex_unlock( &p_fifo->data_lock );
523                 return( -1 );
524             }
525         }
526     }
527
528     l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> p_fifo->b_stereo);
529
530     l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
531 //    fprintf( stderr, "aout debug: %lli (%li);\n", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
532
533     InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->sys.l_rate );
534
535     p_fifo->l_units = (((l_units - (p_fifo->l_unit -
536         (p_fifo->l_start_frame * (p_fifo->l_frame_size >> p_fifo->b_stereo))))
537         * p_aout->sys.l_rate) / l_rate) + 1;
538
539     /* We release the lock before leaving */
540     vlc_mutex_unlock( &p_fifo->data_lock );
541     return( 0 );
542 }
543
544 void aout_Thread_S8_Mono( aout_thread_t * p_aout )
545 {
546 }
547
548 void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
549 {
550 }
551
552 void aout_Thread_U8_Mono( aout_thread_t * p_aout )
553 {
554 }
555
556 void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
557 {
558 }
559
560 void aout_Thread_S16_Mono( aout_thread_t * p_aout )
561 {
562 }
563
564 void aout_Thread_S16_Stereo( aout_thread_t * p_aout )
565 {
566     int i_fifo;
567     long l_buffer, l_buffer_limit;
568     long l_units, l_bytes;
569
570     intf_DbgMsg("adec debug: running audio output thread (%p) (pid == %i)\n", p_aout, getpid());
571
572     /* As the s32_buffer was created with calloc(), we don't have to set this
573      * memory to zero and we can immediately jump into the thread's loop */
574     while ( !p_aout->b_die )
575     {
576         vlc_mutex_lock( &p_aout->fifos_lock );
577         for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
578         {
579             switch ( p_aout->fifo[i_fifo].i_type )
580             {
581                 case AOUT_EMPTY_FIFO:
582                     break;
583
584                 case AOUT_INTF_MONO_FIFO:
585                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
586                     {
587                         l_buffer = 0;
588                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->sys.b_stereo == 1 */
589                         {
590                             p_aout->s32_buffer[l_buffer++] +=
591                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
592                             p_aout->s32_buffer[l_buffer++] +=
593                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
594                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
595                         }
596                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
597                     }
598                     else
599                     {
600                         l_buffer = 0;
601                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->sys.b_stereo == 1 */
602                         {
603                             p_aout->s32_buffer[l_buffer++] +=
604                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
605                             p_aout->s32_buffer[l_buffer++] +=
606                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
607                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
608                         }
609                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
610                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
611                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
612                     }
613                     break;
614
615                 case AOUT_INTF_STEREO_FIFO:
616                     if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
617                     {
618                         l_buffer = 0;
619                         while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->sys.b_stereo == 1 */
620                         {
621                             p_aout->s32_buffer[l_buffer++] +=
622                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
623                             p_aout->s32_buffer[l_buffer++] +=
624                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
625                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
626                         }
627                         p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
628                     }
629                     else
630                     {
631                         l_buffer = 0;
632                         while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->sys.b_stereo */
633                         {
634                             p_aout->s32_buffer[l_buffer++] +=
635                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
636                             p_aout->s32_buffer[l_buffer++] +=
637                                 (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
638                             UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
639                         }
640                         free( p_aout->fifo[i_fifo].buffer ); /* !! */
641                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
642                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
643                     }
644                     break;
645
646                 case AOUT_ADEC_MONO_FIFO:
647                     if ( p_aout->fifo[i_fifo].b_die )
648                     {
649                         free( p_aout->fifo[i_fifo].buffer );
650                         free( p_aout->fifo[i_fifo].date );
651                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
652                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
653                         continue;
654                     }
655
656                     l_units = p_aout->l_units;
657                     l_buffer = 0;
658                     while ( l_units > 0 )
659                     {
660                         if ( !p_aout->fifo[i_fifo].b_next_frame )
661                         {
662                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->sys.l_rate))) )
663                             {
664                                 break;
665                             }
666                         }
667
668                         if ( p_aout->fifo[i_fifo].l_units > l_units )
669                         {
670                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->sys.b_stereo == 1 */
671                             while ( l_buffer < l_buffer_limit )
672                             {
673                                 p_aout->s32_buffer[l_buffer++] +=
674                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
675                                 p_aout->s32_buffer[l_buffer++] +=
676                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
677
678                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
679                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
680                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
681                                 {
682                                     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                             }
686                             p_aout->fifo[i_fifo].l_units -= l_units;
687                             break;
688                         }
689                         else
690                         {
691                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
692                             /* p_aout->sys.b_stereo == 1 */
693                             while ( l_buffer < l_buffer_limit )
694                             {
695                                 p_aout->s32_buffer[l_buffer++] +=
696                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
697                                 p_aout->s32_buffer[l_buffer++] +=
698                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
699
700                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
701                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
702                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
703                                 {
704                                     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                             }
708                             l_units -= p_aout->fifo[i_fifo].l_units;
709
710                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
711                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
712                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
713                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
714
715                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
716                             p_aout->fifo[i_fifo].l_next_frame += 1;
717                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
718                             p_aout->fifo[i_fifo].b_next_frame = 0;
719                         }
720                     }
721                     break;
722
723                 case AOUT_ADEC_STEREO_FIFO:
724                     if ( p_aout->fifo[i_fifo].b_die )
725                     {
726                         free( p_aout->fifo[i_fifo].buffer );
727                         free( p_aout->fifo[i_fifo].date );
728                         p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
729                         intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
730                         continue;
731                     }
732
733                     l_units = p_aout->l_units;
734                     l_buffer = 0;
735                     while ( l_units > 0 )
736                     {
737                         if ( !p_aout->fifo[i_fifo].b_next_frame )
738                         {
739                             if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->sys.l_rate))) )
740                             {
741                                 break;
742                             }
743                         }
744
745                         if ( p_aout->fifo[i_fifo].l_units > l_units )
746                         {
747                             l_buffer_limit = p_aout->l_units << 1; /* p_aout->sys.b_stereo == 1 */
748                             while ( l_buffer < l_buffer_limit )
749                             {
750                                 p_aout->s32_buffer[l_buffer++] +=
751                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
752                                 p_aout->s32_buffer[l_buffer++] +=
753                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
754
755                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
756                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
757                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
758                                 {
759                                     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                             }
763                             p_aout->fifo[i_fifo].l_units -= l_units;
764                             break;
765                         }
766                         else
767                         {
768                             l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units << 1);
769                             /* p_aout->sys.b_stereo == 1 */
770                             while ( l_buffer < l_buffer_limit )
771                             {
772                                 p_aout->s32_buffer[l_buffer++] +=
773                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
774                                 p_aout->s32_buffer[l_buffer++] +=
775                                     (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
776
777                                 UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
778                                 if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
779                                      ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
780                                 {
781                                     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                             }
785                             l_units -= p_aout->fifo[i_fifo].l_units;
786
787                             vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
788                             p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
789                             vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
790                             vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
791
792                             /* p_aout->fifo[i_fifo].b_start_frame = 1; */
793                             p_aout->fifo[i_fifo].l_next_frame += 1;
794                             p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
795                             p_aout->fifo[i_fifo].b_next_frame = 0;
796                         }
797                     }
798                     break;
799
800                 default:
801                     intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
802                     break;
803             }
804         }
805         vlc_mutex_unlock( &p_aout->fifos_lock );
806
807         l_buffer_limit = p_aout->l_units << 1; /* p_aout->sys.b_stereo == 1 */
808
809         for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
810         {
811             ((s16 *)p_aout->buffer)[l_buffer] = (s16)( p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS );
812             p_aout->s32_buffer[l_buffer] = 0;
813         }
814
815         l_bytes = p_aout->p_sys_getbufinfo( &p_aout->sys );
816         p_aout->date = mdate() + ((((mtime_t)(l_bytes / 4)) * 1000000) / ((mtime_t)p_aout->sys.l_rate)); /* sizeof(s16) << p_aout->sys.b_stereo == 4 */
817         p_aout->p_sys_playsamples( &p_aout->sys, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(s16) );
818         if ( l_bytes > (l_buffer_limit * sizeof(s16)) )
819         {
820             msleep( p_aout->l_msleep );
821         }
822     }
823
824     vlc_mutex_lock( &p_aout->fifos_lock );
825     for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
826     {
827         switch ( p_aout->fifo[i_fifo].i_type )
828         {
829             case AOUT_EMPTY_FIFO:
830                 break;
831
832             case AOUT_INTF_MONO_FIFO:
833             case AOUT_INTF_STEREO_FIFO:
834                 free( p_aout->fifo[i_fifo].buffer ); /* !! */
835                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
836                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
837                 break;
838
839             case AOUT_ADEC_MONO_FIFO:
840             case AOUT_ADEC_STEREO_FIFO:
841                 free( p_aout->fifo[i_fifo].buffer );
842                 free( p_aout->fifo[i_fifo].date );
843                 p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
844                 intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
845                 break;
846
847             default:
848                 break;
849         }
850     }
851     vlc_mutex_unlock( &p_aout->fifos_lock );
852 }
853
854 void aout_Thread_U16_Mono( aout_thread_t * p_aout )
855 {
856 }
857
858 void aout_Thread_U16_Stereo( aout_thread_t * p_aout )
859 {
860 }