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