audio_output.c 65.5 KB
Newer Older
1
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
2
 * audio_output.c : audio output thread
3 4 5
 *****************************************************************************
 * Copyright (C) 1999, 2000 VideoLAN
 *
Renaud Dartus's avatar
 
Renaud Dartus committed
6
 * Authors: Michel Kaempf <maxx@via.ecp.fr>
7 8 9 10 11
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
12
 * 
13 14
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
17
 *
18 19 20
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
21
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
22 23 24 25 26 27 28 29 30 31 32 33 34

/* TODO:
 *
 * - Passer un certain nombre de "fonctions" (genre add_samples) en macro ou
 *   inline
 * - Faire les optimisations dans les fonctions threads :
 *   = Stocker les "petits calculs" dans des variables au lieu de les refaire
 *      chaque boucle
 *   = Utiliser des tables pour les gros calculs
 * - Faire une structure diffrente pour intf/adec fifo
 *
 */

35
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
36
 * Preamble
37
 *****************************************************************************/
38 39
#include "defs.h"

40
#include <unistd.h>                                              /* getpid() */
Michel Kaempf's avatar
Michel Kaempf committed
41

42 43
#include <stdio.h>                                           /* "intf_msg.h" */
#include <stdlib.h>                            /* calloc(), malloc(), free() */
Michel Kaempf's avatar
Michel Kaempf committed
44 45

#include "config.h"
46 47
#include "common.h"
#include "threads.h"
48
#include "mtime.h"                             /* mtime_t, mdate(), msleep() */
49
#include "plugins.h"
Michel Kaempf's avatar
Michel Kaempf committed
50

51
#include "intf_msg.h"                        /* intf_DbgMsg(), intf_ErrMsg() */
Michel Kaempf's avatar
Michel Kaempf committed
52 53

#include "audio_output.h"
Vincent Seguin's avatar
Vincent Seguin committed
54
#include "main.h"
Michel Kaempf's avatar
Michel Kaempf committed
55

56
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
57
 * Local prototypes
58
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
59

Vincent Seguin's avatar
Vincent Seguin committed
60 61
static int aout_SpawnThread( aout_thread_t * p_aout );

Michel Kaempf's avatar
Michel Kaempf committed
62 63 64 65 66 67 68 69 70 71 72 73 74
/* Creating as much aout_Thread functions as configurations is one solution,
 * examining the different cases in the Thread loop of an unique function is
 * another. I chose the first solution. */
void aout_Thread_S8_Mono        ( aout_thread_t * p_aout );
void aout_Thread_U8_Mono        ( aout_thread_t * p_aout );
void aout_Thread_S16_Mono       ( aout_thread_t * p_aout );
void aout_Thread_U16_Mono       ( aout_thread_t * p_aout );
void aout_Thread_S8_Stereo      ( aout_thread_t * p_aout );
void aout_Thread_U8_Stereo      ( aout_thread_t * p_aout );
void aout_Thread_S16_Stereo     ( aout_thread_t * p_aout );
void aout_Thread_U16_Stereo     ( aout_thread_t * p_aout );

static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator );
Michel Kaempf's avatar
Michel Kaempf committed
75
static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date );
Michel Kaempf's avatar
Michel Kaempf committed
76

Sam Hocevar's avatar
Sam Hocevar committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
/*****************************************************************************
 * InitializeIncrement
 *****************************************************************************/
static __inline__ void InitializeIncrement( aout_increment_t * p_increment, long l_numerator, long l_denominator )
{
    p_increment->l_remainder = -l_denominator;

    p_increment->l_euclidean_integer = 0;
    while ( l_numerator >= l_denominator )
    {
        p_increment->l_euclidean_integer++;
        l_numerator -= l_denominator;
    }

    p_increment->l_euclidean_remainder = l_numerator;

    p_increment->l_euclidean_denominator = l_denominator;
}

96
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
97
 * aout_CreateThread: initialize audio thread
98
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
99
aout_thread_t *aout_CreateThread( int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
100
{
101
    aout_thread_t * p_aout;                             /* thread descriptor */
102 103
    typedef void    ( aout_getplugin_t ) ( aout_thread_t * p_aout );
    int             i_index;
Sam Hocevar's avatar
Sam Hocevar committed
104
    int             i_best_index = 0, i_best_score = 0;
105
#if 0
Sam Hocevar's avatar
Sam Hocevar committed
106
    int             i_status;                               /* thread status */
107
#endif
108

Vincent Seguin's avatar
Vincent Seguin committed
109 110 111
    /* Allocate descriptor */
    p_aout = (aout_thread_t *) malloc( sizeof(aout_thread_t) );
    if( p_aout == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
112
    {
Vincent Seguin's avatar
Vincent Seguin committed
113
        return( NULL );
Michel Kaempf's avatar
Michel Kaempf committed
114 115
    }

116 117
    /* Get a suitable audio plugin */
    for( i_index = 0 ; i_index < p_main->p_bank->i_plugin_count ; i_index++ )
118
    {
119 120 121 122 123 124
        /* If there's a plugin in p_info ... */
        if( p_main->p_bank->p_info[ i_index ] != NULL )
        {
            /* ... and if this plugin provides the functions we want ... */
            if( p_main->p_bank->p_info[ i_index ]->aout_GetPlugin != NULL )
            {
Sam Hocevar's avatar
Sam Hocevar committed
125 126 127 128 129 130 131
                /* ... and if this plugin has a good score ... */
                if( p_main->p_bank->p_info[ i_index ]->i_score > i_best_score )
                {
                    /* ... then take it */
                    i_best_score = p_main->p_bank->p_info[ i_index ]->i_score;
                    i_best_index = i_index;
                }
132 133
            }
        }
134
    }
135

Sam Hocevar's avatar
Sam Hocevar committed
136 137 138 139 140 141 142 143 144 145
    if( i_best_score == 0 )
    {
        free( p_aout );
        return( NULL );
    }

    /* Get the plugin functions */
    ( (aout_getplugin_t *)
      p_main->p_bank->p_info[ i_best_index ]->aout_GetPlugin )( p_aout );

146
    /*
147
     * Initialize audio device
Vincent Seguin's avatar
Vincent Seguin committed
148
     */
149
    if ( p_aout->p_sys_open( p_aout ) )
Vincent Seguin's avatar
Vincent Seguin committed
150 151 152 153
    {
        free( p_aout );
        return( NULL );
    }
154

155 156 157
    p_aout->b_stereo = ( p_aout->i_channels == 2 ) ? 1 : 0; /* FIXME: only works
                                                   for i_channels == 1 or 2 ??*/

158
    if ( p_aout->p_sys_reset( p_aout ) )
Michel Kaempf's avatar
Michel Kaempf committed
159
    {
160 161 162
        p_aout->p_sys_close( p_aout );
        free( p_aout );
        return( NULL );
Michel Kaempf's avatar
Michel Kaempf committed
163
    }
164
    if ( p_aout->p_sys_setformat( p_aout ) )
Michel Kaempf's avatar
Michel Kaempf committed
165
    {
166 167 168
        p_aout->p_sys_close( p_aout );
        free( p_aout );
        return( NULL );
Michel Kaempf's avatar
Michel Kaempf committed
169
    }
170
    if ( p_aout->p_sys_setchannels( p_aout ) )
Michel Kaempf's avatar
Michel Kaempf committed
171
    {
172 173
        p_aout->p_sys_close( p_aout );
        free( p_aout );
Vincent Seguin's avatar
Vincent Seguin committed
174
        return( NULL );
Michel Kaempf's avatar
Michel Kaempf committed
175
    }
176
    if ( p_aout->p_sys_setrate( p_aout ) )
Michel Kaempf's avatar
Michel Kaempf committed
177
    {
178 179 180
        p_aout->p_sys_close( p_aout );
        free( p_aout );
        return( NULL );
Michel Kaempf's avatar
Michel Kaempf committed
181
    }
182

Renaud Dartus's avatar
Renaud Dartus committed
183
    /* Initialize the volume level */
184
    p_aout->vol = VOLUME_DEFAULT;
Renaud Dartus's avatar
 
Renaud Dartus committed
185
    
186 187 188
    /* FIXME: maybe it would be cleaner to change SpawnThread prototype
     * see vout to handle status correctly ?? however, it is not critical since
     * this thread is only called in main and all calls are blocking */
Vincent Seguin's avatar
Vincent Seguin committed
189 190
    if( aout_SpawnThread( p_aout ) )
    {
191 192 193
        p_aout->p_sys_close( p_aout );
        free( p_aout );
        return( NULL );
Vincent Seguin's avatar
Vincent Seguin committed
194 195 196
    }

    return( p_aout );
Michel Kaempf's avatar
Michel Kaempf committed
197 198
}

199
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
200
 * aout_SpawnThread
201
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
202
static int aout_SpawnThread( aout_thread_t * p_aout )
Michel Kaempf's avatar
Michel Kaempf committed
203
{
Vincent Seguin's avatar
Vincent Seguin committed
204 205 206
    int             i_fifo;
    long            l_bytes;
    void *          aout_thread = NULL;
Michel Kaempf's avatar
Michel Kaempf committed
207 208 209 210 211

    intf_DbgMsg("aout debug: spawning audio output thread (%p)\n", p_aout);

    /* We want the audio output thread to live */
    p_aout->b_die = 0;
Sam Hocevar's avatar
Sam Hocevar committed
212
    p_aout->b_active = 1;
Michel Kaempf's avatar
Michel Kaempf committed
213 214

    /* Initialize the fifos lock */
215
    vlc_mutex_init( &p_aout->fifos_lock );
Michel Kaempf's avatar
Michel Kaempf committed
216 217 218 219
    /* Initialize audio fifos : set all fifos as empty and initialize locks */
    for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
    {
        p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
220 221
        vlc_mutex_init( &p_aout->fifo[i_fifo].data_lock );
        vlc_cond_init( &p_aout->fifo[i_fifo].data_wait );
Michel Kaempf's avatar
Michel Kaempf committed
222 223 224 225 226
    }

    /* Compute the size (in audio units) of the audio output buffer. Although
     * AOUT_BUFFER_DURATION is given in microseconds, the output rate is given
     * in Hz, that's why we need to divide by 10^6 microseconds (1 second) */
227 228
    p_aout->l_units = (long)( ((s64)p_aout->l_rate * AOUT_BUFFER_DURATION) / 1000000 );
    p_aout->l_msleep = (long)( ((s64)p_aout->l_units * 1000000) / (s64)p_aout->l_rate );
Michel Kaempf's avatar
Michel Kaempf committed
229 230 231

    /* Make aout_thread point to the right thread function, and compute the
     * byte size of the audio output buffer */
232
    switch ( p_aout->i_channels )
Michel Kaempf's avatar
Michel Kaempf committed
233 234
    {
        /* Audio output is mono */
235 236
        case 1:
            switch ( p_aout->i_format )
Michel Kaempf's avatar
Michel Kaempf committed
237
            {
238
                case AOUT_FMT_U8:
Michel Kaempf's avatar
Michel Kaempf committed
239 240 241 242
                    l_bytes = 1 * sizeof(u8) * p_aout->l_units;
                    aout_thread = (void *)aout_Thread_U8_Mono;
                    break;

243
                case AOUT_FMT_S8:
Michel Kaempf's avatar
Michel Kaempf committed
244 245 246 247
                    l_bytes = 1 * sizeof(s8) * p_aout->l_units;
                    aout_thread = (void *)aout_Thread_S8_Mono;
                    break;

248 249
                case AOUT_FMT_U16_LE:
                case AOUT_FMT_U16_BE:
Michel Kaempf's avatar
Michel Kaempf committed
250 251 252 253
                    l_bytes = 1 * sizeof(u16) * p_aout->l_units;
                    aout_thread = (void *)aout_Thread_U16_Mono;
                    break;

254 255
                case AOUT_FMT_S16_LE:
                case AOUT_FMT_S16_BE:
Michel Kaempf's avatar
Michel Kaempf committed
256 257 258 259 260
                    l_bytes = 1 * sizeof(s16) * p_aout->l_units;
                    aout_thread = (void *)aout_Thread_S16_Mono;
                    break;

                default:
261 262 263
                    intf_ErrMsg( "aout error: unknown audio output format (%i)\n",
                                 p_aout->i_format );
                    return( -1 );
Michel Kaempf's avatar
Michel Kaempf committed
264 265 266 267
            }
            break;

        /* Audio output is stereo */
268 269
        case 2:
            switch ( p_aout->i_format )
Michel Kaempf's avatar
Michel Kaempf committed
270
            {
271
                case AOUT_FMT_U8:
Michel Kaempf's avatar
Michel Kaempf committed
272 273 274 275
                    l_bytes = 2 * sizeof(u8) * p_aout->l_units;
                    aout_thread = (void *)aout_Thread_U8_Stereo;
                    break;

276
                case AOUT_FMT_S8:
Michel Kaempf's avatar
Michel Kaempf committed
277 278 279 280
                    l_bytes = 2 * sizeof(s8) * p_aout->l_units;
                    aout_thread = (void *)aout_Thread_S8_Stereo;
                    break;

281 282
                case AOUT_FMT_U16_LE:
                case AOUT_FMT_U16_BE:
Michel Kaempf's avatar
Michel Kaempf committed
283 284 285 286
                    l_bytes = 2 * sizeof(u16) * p_aout->l_units;
                    aout_thread = (void *)aout_Thread_U16_Stereo;
                    break;

287 288
                case AOUT_FMT_S16_LE:
                case AOUT_FMT_S16_BE:
Michel Kaempf's avatar
Michel Kaempf committed
289 290 291 292 293 294
                    l_bytes = 2 * sizeof(s16) * p_aout->l_units;
                    aout_thread = (void *)aout_Thread_S16_Stereo;
                    break;

                default:
                    intf_ErrMsg("aout error: unknown audio output format (%i)\n",
295
                        p_aout->i_format);
Michel Kaempf's avatar
Michel Kaempf committed
296 297 298 299 300 301
                    return( -1 );
            }
            break;

        default:
            intf_ErrMsg("aout error: unknown number of audio channels (%i)\n",
302
                p_aout->i_channels );
Michel Kaempf's avatar
Michel Kaempf committed
303 304 305 306 307 308 309 310 311 312
            return( -1 );
    }

    /* Allocate the memory needed by the audio output buffers, and set to zero
     * the s32 buffer's memory */
    if ( (p_aout->buffer = malloc(l_bytes)) == NULL )
    {
        intf_ErrMsg("aout error: not enough memory to create the output buffer\n");
        return( -1 );
    }
313
    if ( (p_aout->s32_buffer = (s32 *)calloc(p_aout->l_units, sizeof(s32) << ( p_aout->b_stereo))) == NULL )
Michel Kaempf's avatar
Michel Kaempf committed
314 315 316 317 318 319 320 321
    {
        intf_ErrMsg("aout error: not enough memory to create the s32 output buffer\n");
        free( p_aout->buffer );
        return( -1 );
    }

    /* Before launching the thread, we try to predict the date of the first
     * audio unit in the first output buffer */
322
    p_aout->date = mdate() - 1000000;
Michel Kaempf's avatar
Michel Kaempf committed
323 324

    /* Launch the thread */
Vincent Seguin's avatar
Vincent Seguin committed
325
    if ( vlc_thread_create( &p_aout->thread_id, "audio output", (vlc_thread_func_t)aout_thread, p_aout ) )
Michel Kaempf's avatar
Michel Kaempf committed
326 327 328 329 330 331 332 333 334 335 336
    {
        intf_ErrMsg("aout error: can't spawn audio output thread (%p)\n", p_aout);
        free( p_aout->buffer );
        free( p_aout->s32_buffer );
        return( -1 );
    }

    intf_DbgMsg("aout debug: audio output thread (%p) spawned\n", p_aout);
    return( 0 );
}

337
/*****************************************************************************
Vincent Seguin's avatar
Vincent Seguin committed
338
 * aout_DestroyThread
339
 *****************************************************************************/
Vincent Seguin's avatar
Vincent Seguin committed
340
void aout_DestroyThread( aout_thread_t * p_aout, int *pi_status )
Michel Kaempf's avatar
Michel Kaempf committed
341
{
342
    /* FIXME: pi_status is not handled correctly: check vout how to do!?? */
Vincent Seguin's avatar
Vincent Seguin committed
343

Michel Kaempf's avatar
Michel Kaempf committed
344 345 346 347
    intf_DbgMsg("aout debug: requesting termination of audio output thread (%p)\n", p_aout);

    /* Ask thread to kill itself and wait until it's done */
    p_aout->b_die = 1;
348
    vlc_thread_join( p_aout->thread_id ); /* only if pi_status is NULL */
Michel Kaempf's avatar
Michel Kaempf committed
349 350 351 352 353

    /* Free the allocated memory */
    free( p_aout->buffer );
    free( p_aout->s32_buffer );

Vincent Seguin's avatar
Vincent Seguin committed
354
    /* Free the structure */
355 356
    p_aout->p_sys_close( p_aout );
    intf_DbgMsg("aout debug: audio device (%s) closed\n", p_aout->psz_device);
357 358

    /* Free structure */
Vincent Seguin's avatar
Vincent Seguin committed
359
    free( p_aout );
Michel Kaempf's avatar
Michel Kaempf committed
360 361
}

362
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
363
 * aout_CreateFifo
364
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
365 366 367 368 369
aout_fifo_t * aout_CreateFifo( aout_thread_t * p_aout, aout_fifo_t * p_fifo )
{
    int i_fifo;

    /* Take the fifos lock */
370
    vlc_mutex_lock( &p_aout->fifos_lock );
Michel Kaempf's avatar
Michel Kaempf committed
371 372 373 374 375

    /* Looking for a free fifo structure */
    for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
    {
        if ( p_aout->fifo[i_fifo].i_type == AOUT_EMPTY_FIFO)
376
        {
Michel Kaempf's avatar
Michel Kaempf committed
377 378 379 380 381 382
            break;
        }
    }
    if ( i_fifo == AOUT_MAX_FIFOS )
    {
        intf_ErrMsg("aout error: no empty fifo available\n");
383
        vlc_mutex_unlock( &p_aout->fifos_lock );
Michel Kaempf's avatar
Michel Kaempf committed
384 385 386 387 388 389 390 391
        return( NULL );
    }

    /* Initialize the new fifo structure */
    switch ( p_aout->fifo[i_fifo].i_type = p_fifo->i_type )
    {
        case AOUT_INTF_MONO_FIFO:
        case AOUT_INTF_STEREO_FIFO:
392
            p_aout->fifo[i_fifo].b_die = 0;
Michel Kaempf's avatar
Michel Kaempf committed
393

394 395 396
            p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
            p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
            p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;
Michel Kaempf's avatar
Michel Kaempf committed
397 398 399 400

            p_aout->fifo[i_fifo].buffer = p_fifo->buffer;

            p_aout->fifo[i_fifo].l_unit = 0;
401
            InitializeIncrement( &p_aout->fifo[i_fifo].unit_increment, p_fifo->l_rate, p_aout->l_rate );
Michel Kaempf's avatar
Michel Kaempf committed
402 403 404 405 406
            p_aout->fifo[i_fifo].l_units = p_fifo->l_units;
            break;

        case AOUT_ADEC_MONO_FIFO:
        case AOUT_ADEC_STEREO_FIFO:
407
            p_aout->fifo[i_fifo].b_die = 0;
Michel Kaempf's avatar
Michel Kaempf committed
408

409
            p_aout->fifo[i_fifo].i_channels = p_fifo->i_channels;
410
            p_aout->fifo[i_fifo].b_stereo = p_fifo->b_stereo;
Michel Kaempf's avatar
Michel Kaempf committed
411 412
            p_aout->fifo[i_fifo].l_rate = p_fifo->l_rate;

413
            p_aout->fifo[i_fifo].l_frame_size = p_fifo->l_frame_size;
Michel Kaempf's avatar
Michel Kaempf committed
414 415 416 417
            /* Allocate the memory needed to store the audio frames. As the
             * fifo is a rotative fifo, we must be able to find out whether the
             * fifo is full or empty, that's why we must in fact allocate memory
             * for (AOUT_FIFO_SIZE+1) audio frames. */
418 419
            if ( (p_aout->fifo[i_fifo].buffer = malloc( sizeof(s16)*(AOUT_FIFO_SIZE+1)*p_fifo->l_frame_size )) == NULL )
            {
Michel Kaempf's avatar
Michel Kaempf committed
420 421
                intf_ErrMsg("aout error: not enough memory to create the frames buffer\n");
                p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
422 423 424
                vlc_mutex_unlock( &p_aout->fifos_lock );
                return( NULL );
            }
Michel Kaempf's avatar
Michel Kaempf committed
425 426 427 428 429 430 431

            /* Allocate the memory needed to store the dates of the frames */
            if ( (p_aout->fifo[i_fifo].date = (mtime_t *)malloc( sizeof(mtime_t)*(AOUT_FIFO_SIZE+1) )) == NULL )
            {
                intf_ErrMsg("aout error: not enough memory to create the dates buffer\n");
                free( p_aout->fifo[i_fifo].buffer );
                p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
432
                vlc_mutex_unlock( &p_aout->fifos_lock );
Michel Kaempf's avatar
Michel Kaempf committed
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
                return( NULL );
            }

            /* Set the fifo's buffer as empty (the first frame that is to be
             * played is also the first frame that is not to be played) */
            p_aout->fifo[i_fifo].l_start_frame = 0;
            /* p_aout->fifo[i_fifo].l_next_frame = 0; */
            p_aout->fifo[i_fifo].l_end_frame = 0;

            /* Waiting for the audio decoder to compute enough frames to work
             * out the fifo's current rate (as soon as the decoder has decoded
             * enough frames, the members of the fifo structure that are not
             * initialized now will be calculated) */
            p_aout->fifo[i_fifo].b_start_frame = 0;
            p_aout->fifo[i_fifo].b_next_frame = 0;
            break;

        default:
            intf_ErrMsg("aout error: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
            p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO;
453
            vlc_mutex_unlock( &p_aout->fifos_lock );
Michel Kaempf's avatar
Michel Kaempf committed
454 455 456 457
            return( NULL );
    }

    /* Release the fifos lock */
458
    vlc_mutex_unlock( &p_aout->fifos_lock );
Michel Kaempf's avatar
Michel Kaempf committed
459 460 461 462 463 464

    /* Return the pointer to the fifo structure */
    intf_DbgMsg("aout debug: audio output fifo (%p) allocated\n", &p_aout->fifo[i_fifo]);
    return( &p_aout->fifo[i_fifo] );
}

465
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
466
 * aout_DestroyFifo
467
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
468 469 470 471 472 473 474 475 476
void aout_DestroyFifo( aout_fifo_t * p_fifo )
{
    intf_DbgMsg("aout debug: requesting destruction of audio output fifo (%p)\n", p_fifo);
    p_fifo->b_die = 1;
}

/* Here are the local macros */

#define UPDATE_INCREMENT( increment, integer ) \
477
    if ( ((increment).l_remainder += (increment).l_euclidean_remainder) >= 0 )\
Michel Kaempf's avatar
Michel Kaempf committed
478 479 480 481 482 483 484 485 486 487 488
    { \
        (integer) += (increment).l_euclidean_integer + 1; \
        (increment).l_remainder -= (increment).l_euclidean_denominator; \
    } \
    else \
    { \
        (integer) += (increment).l_euclidean_integer; \
    }

/* Following functions are local */

489
/*****************************************************************************
Michel Kaempf's avatar
Michel Kaempf committed
490
 * NextFrame
491
 *****************************************************************************/
Michel Kaempf's avatar
Michel Kaempf committed
492
static __inline__ int NextFrame( aout_thread_t * p_aout, aout_fifo_t * p_fifo, mtime_t aout_date )
Michel Kaempf's avatar
Michel Kaempf committed
493 494 495 496
{
    long l_units, l_rate;

    /* We take the lock */
497
    vlc_mutex_lock( &p_fifo->data_lock );
Michel Kaempf's avatar
Michel Kaempf committed
498 499 500 501 502 503 504 505 506 507

    /* Are we looking for a dated start frame ? */
    if ( !p_fifo->b_start_frame )
    {
        while ( p_fifo->l_start_frame != p_fifo->l_end_frame )
        {
            if ( p_fifo->date[p_fifo->l_start_frame] != LAST_MDATE )
            {
                p_fifo->b_start_frame = 1;
                p_fifo->l_next_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
508
                p_fifo->l_unit = p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
Michel Kaempf's avatar
Michel Kaempf committed
509 510 511 512
                break;
            }
            p_fifo->l_start_frame = (p_fifo->l_start_frame + 1) & AOUT_FIFO_SIZE;
        }
Michel Kaempf's avatar
Michel Kaempf committed
513

Michel Kaempf's avatar
Michel Kaempf committed
514 515
        if ( p_fifo->l_start_frame == p_fifo->l_end_frame )
        {
516
            vlc_mutex_unlock( &p_fifo->data_lock );
Michel Kaempf's avatar
Michel Kaempf committed
517 518 519
            return( -1 );
        }
    }
Michel Kaempf's avatar
Michel Kaempf committed
520

Michel Kaempf's avatar
Michel Kaempf committed
521
    /* We are looking for the next dated frame */
522
    /* FIXME : is the output fifo full ?? */
Michel Kaempf's avatar
Michel Kaempf committed
523
    while ( !p_fifo->b_next_frame )
Michel Kaempf's avatar
Michel Kaempf committed
524
    {
525
        while ( p_fifo->l_next_frame != p_fifo->l_end_frame )
Michel Kaempf's avatar
Michel Kaempf committed
526
        {
527
            if ( p_fifo->date[p_fifo->l_next_frame] != LAST_MDATE )
Michel Kaempf's avatar
Michel Kaempf committed
528 529 530
            {
                p_fifo->b_next_frame = 1;
                break;
Michel Kaempf's avatar
Michel Kaempf committed
531
            }
Michel Kaempf's avatar
Michel Kaempf committed
532
            p_fifo->l_next_frame = (p_fifo->l_next_frame + 1) & AOUT_FIFO_SIZE;
Michel Kaempf's avatar
Michel Kaempf committed
533
        }
534

Michel Kaempf's avatar
Michel Kaempf committed
535
        while ( p_fifo->l_next_frame == p_fifo->l_end_frame )
Michel Kaempf's avatar
Michel Kaempf committed
536
        {
Michel Kaempf's avatar
Michel Kaempf committed
537 538
            vlc_cond_wait( &p_fifo->data_wait, &p_fifo->data_lock );
            if ( p_fifo->b_die )
539 540 541 542
            {
                vlc_mutex_unlock( &p_fifo->data_lock );
                return( -1 );
            }
Michel Kaempf's avatar
Michel Kaempf committed
543 544 545
        }
    }

546
    l_units = ((p_fifo->l_next_frame - p_fifo->l_start_frame) & AOUT_FIFO_SIZE) * (p_fifo->l_frame_size >> (p_fifo->b_stereo));
Michel Kaempf's avatar
Michel Kaempf committed
547

548
    l_rate = p_fifo->l_rate + ((aout_date - p_fifo->date[p_fifo->l_start_frame]) / 256);
Renaud Dartus's avatar
Renaud Dartus committed
549
    intf_DbgMsg( "aout debug: %lli (%li);\n", aout_date - p_fifo->date[p_fifo->l_start_frame], l_rate );
Michel Kaempf's avatar
Michel Kaempf committed
550

551
    InitializeIncrement( &p_fifo->unit_increment, l_rate, p_aout->l_rate );
Michel Kaempf's avatar
Michel Kaempf committed
552 553

    p_fifo->l_units = (((l_units - (p_fifo->l_unit -
554
        (p_fifo->l_start_frame * (p_fifo->l_frame_size >> (p_fifo->b_stereo)))))
555
        * p_aout->l_rate) / l_rate) + 1;
Michel Kaempf's avatar
Michel Kaempf committed
556 557

    /* We release the lock before leaving */
558
    vlc_mutex_unlock( &p_fifo->data_lock );
Michel Kaempf's avatar
Michel Kaempf committed
559 560 561 562 563 564 565 566 567 568 569 570 571
    return( 0 );
}

void aout_Thread_S8_Mono( aout_thread_t * p_aout )
{
}

void aout_Thread_S8_Stereo( aout_thread_t * p_aout )
{
}

void aout_Thread_U8_Mono( aout_thread_t * p_aout )
{
Renaud Dartus's avatar
 
Renaud Dartus committed
572 573 574 575
    int i_fifo;
    long l_buffer, l_buffer_limit;
    long l_units, l_bytes;

Renaud Dartus's avatar
Renaud Dartus committed
576
    intf_DbgMsg("adec debug: running audio output U8_M_thread (%p) (pid == %i)\n", p_aout, getpid());
Renaud Dartus's avatar
 
Renaud Dartus committed
577 578 579 580 581 582 583

    /* As the s32_buffer was created with calloc(), we don't have to set this
     * memory to zero and we can immediately jump into the thread's loop */
    while ( !p_aout->b_die )
    {
        vlc_mutex_lock( &p_aout->fifos_lock );
        for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
584
        {
Renaud Dartus's avatar
 
Renaud Dartus committed
585
            switch ( p_aout->fifo[i_fifo].i_type )
586
            {
Renaud Dartus's avatar
Renaud Dartus committed
587
                case AOUT_EMPTY_FIFO:
Renaud Dartus's avatar
 
Renaud Dartus committed
588 589
                    break;

Renaud Dartus's avatar
Renaud Dartus committed
590
                case AOUT_INTF_MONO_FIFO:
Renaud Dartus's avatar
 
Renaud Dartus committed
591
                    if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
592
                    {
Renaud Dartus's avatar
 
Renaud Dartus committed
593
                        l_buffer = 0;
Renaud Dartus's avatar
Renaud Dartus committed
594
                        while ( l_buffer < (p_aout->l_units) ) /* p_aout->b_stereo == 0 */
595
                        {
Renaud Dartus's avatar
 
Renaud Dartus committed
596 597 598 599 600 601 602 603 604
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
                            UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                        }
                        p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
                    }
                    else
605
                    {
Renaud Dartus's avatar
 
Renaud Dartus committed
606
                        l_buffer = 0;
Renaud Dartus's avatar
Renaud Dartus committed
607
                        while ( l_buffer < (p_aout->fifo[i_fifo].l_units) ) /* p_aout->b_stereo == 0 */
608
                        {
Renaud Dartus's avatar
 
Renaud Dartus committed
609 610 611 612 613 614 615 616 617 618 619 620
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
                            UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                        }
                        free( p_aout->fifo[i_fifo].buffer ); /* !! */
                        p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
                        intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
                    }
                    break;

                case AOUT_INTF_STEREO_FIFO:
                    if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
621
                    {
Renaud Dartus's avatar
 
Renaud Dartus committed
622
                        l_buffer = 0;
Renaud Dartus's avatar
Renaud Dartus committed
623
                        while ( l_buffer < (p_aout->l_units) ) /* p_aout->b_stereo == 0 */
624
                        {
Renaud Dartus's avatar
Renaud Dartus committed
625
                            /* I mix half left - half right */
Renaud Dartus's avatar
 
Renaud Dartus committed
626
                            p_aout->s32_buffer[l_buffer++] +=
Renaud Dartus's avatar
Renaud Dartus committed
627 628
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
Renaud Dartus's avatar
 
Renaud Dartus committed
629 630 631 632 633
                            UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                        }
                        p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
                    }
                    else
634
                    {
Renaud Dartus's avatar
 
Renaud Dartus committed
635
                        l_buffer = 0;
Renaud Dartus's avatar
Renaud Dartus committed
636
                        while ( l_buffer < (p_aout->fifo[i_fifo].l_units) ) /* p_aout->b_stereo == 0 */
637
                        {
Renaud Dartus's avatar
Renaud Dartus committed
638
                            /* I mix half left - half right */
Renaud Dartus's avatar
 
Renaud Dartus committed
639
                            p_aout->s32_buffer[l_buffer++] +=
Renaud Dartus's avatar
Renaud Dartus committed
640 641
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
Renaud Dartus's avatar
 
Renaud Dartus committed
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
                            UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                        }
                        free( p_aout->fifo[i_fifo].buffer ); /* !! */
                        p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
                        intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
                    }
                    break;

                case AOUT_ADEC_MONO_FIFO:
                    if ( p_aout->fifo[i_fifo].b_die )
                    {
                        free( p_aout->fifo[i_fifo].buffer );
                        free( p_aout->fifo[i_fifo].date );
                        p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
                        intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
                        continue;
                    }

                    l_units = p_aout->l_units;
                    l_buffer = 0;
                    while ( l_units > 0 )
                    {
                        if ( !p_aout->fifo[i_fifo].b_next_frame )
                        {
                            if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
                            {
                                break;
                            }
                        }

                        if ( p_aout->fifo[i_fifo].l_units > l_units )
                        {
Renaud Dartus's avatar
Renaud Dartus committed
674
                            l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
Renaud Dartus's avatar
 
Renaud Dartus committed
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
                            while ( l_buffer < l_buffer_limit )
                            {
                                p_aout->s32_buffer[l_buffer++] +=
                                    (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );

                                UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                                if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
                                     ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
                                {
                                    p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
                                        ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
                                }
                            }
                            p_aout->fifo[i_fifo].l_units -= l_units;
                            break;
                        }
                        else
                        {
Renaud Dartus's avatar
Renaud Dartus committed
693 694
                            l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units);
                            /* p_aout->b_stereo == 0 */
Renaud Dartus's avatar
 
Renaud Dartus committed
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743
                            while ( l_buffer < l_buffer_limit )
                            {
                                p_aout->s32_buffer[l_buffer++] +=
                                    (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );

                                UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                                if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 0 */
                                     ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0)) )
                                {
                                    p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 0 */
                                        ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 0));
                                }
                            }
                            l_units -= p_aout->fifo[i_fifo].l_units;

                            vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
                            p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
                            vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
                            vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );

                            /* p_aout->fifo[i_fifo].b_start_frame = 1; */
                            p_aout->fifo[i_fifo].l_next_frame += 1;
                            p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
                            p_aout->fifo[i_fifo].b_next_frame = 0;
                        }
                    }
                    break;

                case AOUT_ADEC_STEREO_FIFO:
                    if ( p_aout->fifo[i_fifo].b_die )
                    {
                        free( p_aout->fifo[i_fifo].buffer );
                        free( p_aout->fifo[i_fifo].date );
                        p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
                        intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
                        continue;
                    }

                    l_units = p_aout->l_units;
                    l_buffer = 0;
                    while ( l_units > 0 )
                    {
                        if ( !p_aout->fifo[i_fifo].b_next_frame )
                        {
                            if ( NextFrame(p_aout, &p_aout->fifo[i_fifo], p_aout->date + ((((mtime_t)(l_buffer >> 1)) * 1000000) / ((mtime_t)p_aout->l_rate))) )
                            {
                                break;
                            }
                        }
Renaud Dartus's avatar
Renaud Dartus committed
744

Renaud Dartus's avatar
 
Renaud Dartus committed
745 746
                        if ( p_aout->fifo[i_fifo].l_units > l_units )
                        {
Renaud Dartus's avatar
Renaud Dartus committed
747
                            l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */
Renaud Dartus's avatar
 
Renaud Dartus committed
748 749
                            while ( l_buffer < l_buffer_limit )
                            {
Renaud Dartus's avatar
Renaud Dartus committed
750
                                /* I mix half left - half right */
Renaud Dartus's avatar
 
Renaud Dartus committed
751
                                p_aout->s32_buffer[l_buffer++] +=
Renaud Dartus's avatar
Renaud Dartus committed
752 753
                                    (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
                                    (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
Renaud Dartus's avatar
 
Renaud Dartus committed
754 755 756

                                UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                                if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
Renaud Dartus's avatar
Renaud Dartus committed
757
                                     ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
Renaud Dartus's avatar
 
Renaud Dartus committed
758 759
                                {
                                    p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
Renaud Dartus's avatar
Renaud Dartus committed
760
                                        ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
Renaud Dartus's avatar
 
Renaud Dartus committed
761 762 763 764 765 766 767
                                }
                            }
                            p_aout->fifo[i_fifo].l_units -= l_units;
                            break;
                        }
                        else
                        {
Renaud Dartus's avatar
Renaud Dartus committed
768 769
                            l_buffer_limit = l_buffer + (p_aout->fifo[i_fifo].l_units);
                            /* p_aout->b_stereo == 0 */
Renaud Dartus's avatar
 
Renaud Dartus committed
770 771
                            while ( l_buffer < l_buffer_limit )
                            {
Renaud Dartus's avatar
Renaud Dartus committed
772
                                /* I mix half left - half right */
Renaud Dartus's avatar
 
Renaud Dartus committed
773
                                p_aout->s32_buffer[l_buffer++] +=
Renaud Dartus's avatar
Renaud Dartus committed
774 775
                                    (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] ) / 2 +
                                    (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] ) / 2;
Renaud Dartus's avatar
 
Renaud Dartus committed
776 777 778

                                UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                                if ( p_aout->fifo[i_fifo].l_unit >= /* p_aout->fifo[i_fifo].b_stereo == 1 */
Renaud Dartus's avatar
Renaud Dartus committed
779
                                     ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1)) )
Renaud Dartus's avatar
 
Renaud Dartus committed
780 781
                                {
                                    p_aout->fifo[i_fifo].l_unit -= /* p_aout->fifo[i_fifo].b_stereo == 1 */
Renaud Dartus's avatar
Renaud Dartus committed
782
                                        ((AOUT_FIFO_SIZE + 1) * (p_aout->fifo[i_fifo].l_frame_size >> 1));
Renaud Dartus's avatar
 
Renaud Dartus committed
783 784 785
                                }
                            }
                            l_units -= p_aout->fifo[i_fifo].l_units;
Renaud Dartus's avatar
Renaud Dartus committed
786

Renaud Dartus's avatar
 
Renaud Dartus committed
787 788 789 790
                            vlc_mutex_lock( &p_aout->fifo[i_fifo].data_lock );
                            p_aout->fifo[i_fifo].l_start_frame = p_aout->fifo[i_fifo].l_next_frame;
                            vlc_cond_signal( &p_aout->fifo[i_fifo].data_wait );
                            vlc_mutex_unlock( &p_aout->fifo[i_fifo].data_lock );
Renaud Dartus's avatar
Renaud Dartus committed
791

Renaud Dartus's avatar
 
Renaud Dartus committed
792 793 794 795 796 797 798 799
                            /* p_aout->fifo[i_fifo].b_start_frame = 1; */
                            p_aout->fifo[i_fifo].l_next_frame += 1;
                            p_aout->fifo[i_fifo].l_next_frame &= AOUT_FIFO_SIZE;
                            p_aout->fifo[i_fifo].b_next_frame = 0;
                        }
                    }
                    break;

Renaud Dartus's avatar
Renaud Dartus committed
800
            default:
Renaud Dartus's avatar
 
Renaud Dartus committed
801 802 803 804 805
                    intf_DbgMsg("aout debug: unknown fifo type (%i)\n", p_aout->fifo[i_fifo].i_type);
                    break;
            }
        }
        vlc_mutex_unlock( &p_aout->fifos_lock );
Renaud Dartus's avatar
Renaud Dartus committed
806 807 808

        l_buffer_limit = p_aout->l_units; /* p_aout->b_stereo == 0 */

Renaud Dartus's avatar
 
Renaud Dartus committed
809
        for ( l_buffer = 0; l_buffer < l_buffer_limit; l_buffer++ )
Renaud Dartus's avatar
Renaud Dartus committed
810 811 812
        {
            ((u8 *)p_aout->buffer)[l_buffer] = (u8)( ( (p_aout->s32_buffer[l_buffer] / AOUT_MAX_FIFOS / 256 ) + 128 ) * p_aout->vol / 256 );
            p_aout->s32_buffer[l_buffer] = 0;
Renaud Dartus's avatar
 
Renaud Dartus committed
813 814
        }
        l_bytes = p_aout->p_sys_getbufinfo( p_aout, l_buffer_limit );
Renaud Dartus's avatar
Renaud Dartus committed
815
        p_aout->date = mdate() + ((((mtime_t)(l_bytes / 1 )) * 1000000) / ((mtime_t)p_aout->l_rate)); /* sizeof(u8) << (p_aout->b_stereo) == 1 */
Renaud Dartus's avatar
 
Renaud Dartus committed
816
        p_aout->p_sys_playsamples( p_aout, (byte_t *)p_aout->buffer, l_buffer_limit * sizeof(u8) );
Renaud Dartus's avatar
Renaud Dartus committed
817
        if ( l_bytes > (l_buffer_limit * sizeof(u8) * 2) ) /* There are 2 channels (left & right) */
Renaud Dartus's avatar
 
Renaud Dartus committed
818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
        {
            msleep( p_aout->l_msleep );
        }
    }

    vlc_mutex_lock( &p_aout->fifos_lock );
    for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
    {
        switch ( p_aout->fifo[i_fifo].i_type )
        {
            case AOUT_EMPTY_FIFO:
                break;

            case AOUT_INTF_MONO_FIFO:
            case AOUT_INTF_STEREO_FIFO:
                free( p_aout->fifo[i_fifo].buffer ); /* !! */
                p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
                intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
                break;

            case AOUT_ADEC_MONO_FIFO:
            case AOUT_ADEC_STEREO_FIFO:
                free( p_aout->fifo[i_fifo].buffer );
                free( p_aout->fifo[i_fifo].date );
                p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
                intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]);
                break;

            default:
                break;
        }
    }
    vlc_mutex_unlock( &p_aout->fifos_lock );
Renaud Dartus's avatar
Renaud Dartus committed
851 852


Michel Kaempf's avatar
Michel Kaempf committed
853 854 855 856
}

void aout_Thread_U8_Stereo( aout_thread_t * p_aout )
{
Renaud Dartus's avatar
 
Renaud Dartus committed
857 858 859 860
    int i_fifo;
    long l_buffer, l_buffer_limit;
    long l_units, l_bytes;

Renaud Dartus's avatar
Renaud Dartus committed
861
    intf_DbgMsg("adec debug: running audio output U8_S_thread (%p) (pid == %i)\n", p_aout, getpid());
Renaud Dartus's avatar
 
Renaud Dartus committed
862 863 864 865 866 867 868

    /* As the s32_buffer was created with calloc(), we don't have to set this
     * memory to zero and we can immediately jump into the thread's loop */
    while ( !p_aout->b_die )
    {
        vlc_mutex_lock( &p_aout->fifos_lock );
        for ( i_fifo = 0; i_fifo < AOUT_MAX_FIFOS; i_fifo++ )
869
        {
Renaud Dartus's avatar
 
Renaud Dartus committed
870
            switch ( p_aout->fifo[i_fifo].i_type )
871 872
            {
                case AOUT_EMPTY_FIFO:
Renaud Dartus's avatar
 
Renaud Dartus committed
873 874
                    break;

875
                case AOUT_INTF_MONO_FIFO:
Renaud Dartus's avatar
 
Renaud Dartus committed
876
                    if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
877
                    {
Renaud Dartus's avatar
 
Renaud Dartus committed
878 879
                        l_buffer = 0;
                        while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
880
                        {
Renaud Dartus's avatar
 
Renaud Dartus committed
881 882 883 884 885 886 887 888 889
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
                            UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                        }
                        p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
                    }
                    else
890
                    {
Renaud Dartus's avatar
 
Renaud Dartus committed
891 892
                        l_buffer = 0;
                        while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
893
                        {
Renaud Dartus's avatar
 
Renaud Dartus committed
894 895 896 897 898 899 900 901 902 903 904 905 906 907
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[p_aout->fifo[i_fifo].l_unit] );
                            UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                        }
                        free( p_aout->fifo[i_fifo].buffer ); /* !! */
                        p_aout->fifo[i_fifo].i_type = AOUT_EMPTY_FIFO; /* !! */
                        intf_DbgMsg("aout debug: audio output fifo (%p) destroyed\n", &p_aout->fifo[i_fifo]); /* !! */
                    }
                    break;

                case AOUT_INTF_STEREO_FIFO:
                    if ( p_aout->fifo[i_fifo].l_units > p_aout->l_units )
908
                    {
Renaud Dartus's avatar
 
Renaud Dartus committed
909 910
                        l_buffer = 0;
                        while ( l_buffer < (p_aout->l_units << 1) ) /* p_aout->b_stereo == 1 */
911
                        {
Renaud Dartus's avatar
 
Renaud Dartus committed
912 913 914 915 916 917 918 919 920
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
                            UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                        }
                        p_aout->fifo[i_fifo].l_units -= p_aout->l_units;
                    }
                    else
921
                    {
Renaud Dartus's avatar
 
Renaud Dartus committed
922 923
                        l_buffer = 0;
                        while ( l_buffer < (p_aout->fifo[i_fifo].l_units << 1) ) /* p_aout->b_stereo == 1 */
924
                        {
Renaud Dartus's avatar
 
Renaud Dartus committed
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit] );
                            p_aout->s32_buffer[l_buffer++] +=
                                (s32)( ((s16 *)p_aout->fifo[i_fifo].buffer)[2*p_aout->fifo[i_fifo].l_unit+1] );
                            UPDATE_INCREMENT( p_aout->fifo[i_fifo].unit_increment, p_aout->fifo[i_fifo].l_unit )
                        }
                        free( p_aout->fifo[i_fifo