mixer.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:14k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * mixer.c : audio output mixing operations
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2004 the VideoLAN team
  5.  * $Id: c8d31fac211cd86cfbebad954b27b72461abeb9e $
  6.  *
  7.  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <stddef.h>
  30. #include <vlc_common.h>
  31. #ifdef HAVE_ALLOCA_H
  32. #   include <alloca.h>
  33. #endif
  34. #include <vlc_aout.h>
  35. #include "aout_internal.h"
  36. /*****************************************************************************
  37.  * aout_MixerNew: prepare a mixer plug-in
  38.  *****************************************************************************
  39.  * Please note that you must hold the mixer lock.
  40.  *****************************************************************************/
  41. int aout_MixerNew( aout_instance_t * p_aout )
  42. {
  43.     p_aout->mixer.p_module = module_need( p_aout, "audio mixer", NULL, false );
  44.     if ( p_aout->mixer.p_module == NULL )
  45.     {
  46.         msg_Err( p_aout, "no suitable audio mixer" );
  47.         return -1;
  48.     }
  49.     p_aout->mixer.b_error = 0;
  50.     return 0;
  51. }
  52. /*****************************************************************************
  53.  * aout_MixerDelete: delete the mixer
  54.  *****************************************************************************
  55.  * Please note that you must hold the mixer lock.
  56.  *****************************************************************************/
  57. void aout_MixerDelete( aout_instance_t * p_aout )
  58. {
  59.     if ( p_aout->mixer.b_error ) return;
  60.     module_unneed( p_aout, p_aout->mixer.p_module );
  61.     p_aout->mixer.b_error = 1;
  62. }
  63. /*****************************************************************************
  64.  * MixBuffer: try to prepare one output buffer
  65.  *****************************************************************************
  66.  * Please note that you must hold the mixer lock.
  67.  *****************************************************************************/
  68. static int MixBuffer( aout_instance_t * p_aout )
  69. {
  70.     int             i, i_first_input = 0;
  71.     aout_buffer_t * p_output_buffer;
  72.     mtime_t start_date, end_date;
  73.     audio_date_t exact_start_date;
  74.     if ( p_aout->mixer.b_error )
  75.     {
  76.         /* Free all incoming buffers. */
  77.         aout_lock_input_fifos( p_aout );
  78.         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  79.         {
  80.             aout_input_t * p_input = p_aout->pp_inputs[i];
  81.             aout_buffer_t * p_buffer = p_input->fifo.p_first;
  82.             if ( p_input->b_error ) continue;
  83.             while ( p_buffer != NULL )
  84.             {
  85.                 aout_buffer_t * p_next = p_buffer->p_next;
  86.                 aout_BufferFree( p_buffer );
  87.                 p_buffer = p_next;
  88.             }
  89.         }
  90.         aout_unlock_input_fifos( p_aout );
  91.         return -1;
  92.     }
  93.     aout_lock_input_fifos( p_aout );
  94.     aout_lock_output_fifo( p_aout );
  95.     /* Retrieve the date of the next buffer. */
  96.     memcpy( &exact_start_date, &p_aout->output.fifo.end_date,
  97.             sizeof(audio_date_t) );
  98.     start_date = aout_DateGet( &exact_start_date );
  99.     if ( start_date != 0 && start_date < mdate() )
  100.     {
  101.         /* The output is _very_ late. This can only happen if the user
  102.          * pauses the stream (or if the decoder is buggy, which cannot
  103.          * happen :). */
  104.         msg_Warn( p_aout, "output PTS is out of range (%"PRId64"), clearing out",
  105.                   mdate() - start_date );
  106.         aout_FifoSet( p_aout, &p_aout->output.fifo, 0 );
  107.         aout_DateSet( &exact_start_date, 0 );
  108.         start_date = 0;
  109.     }
  110.     aout_unlock_output_fifo( p_aout );
  111.     /* See if we have enough data to prepare a new buffer for the audio
  112.      * output. First : start date. */
  113.     if ( !start_date )
  114.     {
  115.         /* Find the latest start date available. */
  116.         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  117.         {
  118.             aout_input_t * p_input = p_aout->pp_inputs[i];
  119.             aout_fifo_t * p_fifo = &p_input->fifo;
  120.             aout_buffer_t * p_buffer;
  121.             if ( p_input->b_error || p_input->b_paused )
  122.                 continue;
  123.             p_buffer = p_fifo->p_first;
  124.             while ( p_buffer != NULL && p_buffer->start_date < mdate() )
  125.             {
  126.                 msg_Warn( p_aout, "input PTS is out of range (%"PRId64"), "
  127.                           "trashing", mdate() - p_buffer->start_date );
  128.                 p_buffer = aout_FifoPop( p_aout, p_fifo );
  129.                 aout_BufferFree( p_buffer );
  130.                 p_buffer = p_fifo->p_first;
  131.                 p_input->p_first_byte_to_mix = NULL;
  132.             }
  133.             if ( p_buffer == NULL )
  134.             {
  135.                 break;
  136.             }
  137.             if ( !start_date || start_date < p_buffer->start_date )
  138.             {
  139.                 aout_DateSet( &exact_start_date, p_buffer->start_date );
  140.                 start_date = p_buffer->start_date;
  141.             }
  142.         }
  143.         if ( i < p_aout->i_nb_inputs )
  144.         {
  145.             /* Interrupted before the end... We can't run. */
  146.             aout_unlock_input_fifos( p_aout );
  147.             return -1;
  148.         }
  149.     }
  150.     aout_DateIncrement( &exact_start_date, p_aout->output.i_nb_samples );
  151.     end_date = aout_DateGet( &exact_start_date );
  152.     /* Check that start_date and end_date are available for all input
  153.      * streams. */
  154.     for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  155.     {
  156.         aout_input_t * p_input = p_aout->pp_inputs[i];
  157.         aout_fifo_t * p_fifo = &p_input->fifo;
  158.         aout_buffer_t * p_buffer;
  159.         mtime_t prev_date;
  160.         bool b_drop_buffers;
  161.         if ( p_input->b_error || p_input->b_paused )
  162.         {
  163.             if ( i_first_input == i ) i_first_input++;
  164.             continue;
  165.         }
  166.         p_buffer = p_fifo->p_first;
  167.         if ( p_buffer == NULL )
  168.         {
  169.             break;
  170.         }
  171.         /* Check for the continuity of start_date */
  172.         while ( p_buffer != NULL && p_buffer->end_date < start_date - 1 )
  173.         {
  174.             /* We authorize a +-1 because rounding errors get compensated
  175.              * regularly. */
  176.             aout_buffer_t * p_next = p_buffer->p_next;
  177.             msg_Warn( p_aout, "the mixer got a packet in the past (%"PRId64")",
  178.                       start_date - p_buffer->end_date );
  179.             aout_BufferFree( p_buffer );
  180.             p_fifo->p_first = p_buffer = p_next;
  181.             p_input->p_first_byte_to_mix = NULL;
  182.         }
  183.         if ( p_buffer == NULL )
  184.         {
  185.             p_fifo->pp_last = &p_fifo->p_first;
  186.             break;
  187.         }
  188.         /* Check that we have enough samples. */
  189.         for ( ; ; )
  190.         {
  191.             p_buffer = p_fifo->p_first;
  192.             if ( p_buffer == NULL ) break;
  193.             if ( p_buffer->end_date >= end_date ) break;
  194.             /* Check that all buffers are contiguous. */
  195.             prev_date = p_fifo->p_first->end_date;
  196.             p_buffer = p_buffer->p_next;
  197.             b_drop_buffers = 0;
  198.             for ( ; p_buffer != NULL; p_buffer = p_buffer->p_next )
  199.             {
  200.                 if ( prev_date != p_buffer->start_date )
  201.                 {
  202.                     msg_Warn( p_aout,
  203.                               "buffer hole, dropping packets (%"PRId64")",
  204.                               p_buffer->start_date - prev_date );
  205.                     b_drop_buffers = 1;
  206.                     break;
  207.                 }
  208.                 if ( p_buffer->end_date >= end_date ) break;
  209.                 prev_date = p_buffer->end_date;
  210.             }
  211.             if ( b_drop_buffers )
  212.             {
  213.                 aout_buffer_t * p_deleted = p_fifo->p_first;
  214.                 while ( p_deleted != NULL && p_deleted != p_buffer )
  215.                 {
  216.                     aout_buffer_t * p_next = p_deleted->p_next;
  217.                     aout_BufferFree( p_deleted );
  218.                     p_deleted = p_next;
  219.                 }
  220.                 p_fifo->p_first = p_deleted; /* == p_buffer */
  221.             }
  222.             else break;
  223.         }
  224.         if ( p_buffer == NULL ) break;
  225.         p_buffer = p_fifo->p_first;
  226.         if ( !AOUT_FMT_NON_LINEAR( &p_aout->mixer.mixer ) )
  227.         {
  228.             /* Additionally check that p_first_byte_to_mix is well
  229.              * located. */
  230.             mtime_t i_nb_bytes = (start_date - p_buffer->start_date)
  231.                             * p_aout->mixer.mixer.i_bytes_per_frame
  232.                             * p_aout->mixer.mixer.i_rate
  233.                             / p_aout->mixer.mixer.i_frame_length
  234.                             / 1000000;
  235.             ptrdiff_t mixer_nb_bytes;
  236.             if ( p_input->p_first_byte_to_mix == NULL )
  237.             {
  238.                 p_input->p_first_byte_to_mix = p_buffer->p_buffer;
  239.             }
  240.             mixer_nb_bytes = p_input->p_first_byte_to_mix - p_buffer->p_buffer;
  241.             if ( !((i_nb_bytes + p_aout->mixer.mixer.i_bytes_per_frame
  242.                      > mixer_nb_bytes) &&
  243.                    (i_nb_bytes < p_aout->mixer.mixer.i_bytes_per_frame
  244.                      + mixer_nb_bytes)) )
  245.             {
  246.                 msg_Warn( p_aout, "mixer start isn't output start (%"PRId64")",
  247.                           i_nb_bytes - mixer_nb_bytes );
  248.                 /* Round to the nearest multiple */
  249.                 i_nb_bytes /= p_aout->mixer.mixer.i_bytes_per_frame;
  250.                 i_nb_bytes *= p_aout->mixer.mixer.i_bytes_per_frame;
  251.                 if( i_nb_bytes < 0 )
  252.                 {
  253.                     /* Is it really the best way to do it ? */
  254.                     aout_lock_output_fifo( p_aout );
  255.                     aout_FifoSet( p_aout, &p_aout->output.fifo, 0 );
  256.                     aout_DateSet( &exact_start_date, 0 );
  257.                     aout_unlock_output_fifo( p_aout );
  258.                     break;
  259.                 }
  260.                 p_input->p_first_byte_to_mix = p_buffer->p_buffer + i_nb_bytes;
  261.             }
  262.         }
  263.     }
  264.     if ( i < p_aout->i_nb_inputs || i_first_input == p_aout->i_nb_inputs )
  265.     {
  266.         /* Interrupted before the end... We can't run. */
  267.         aout_unlock_input_fifos( p_aout );
  268.         return -1;
  269.     }
  270.     /* Run the mixer. */
  271.     aout_BufferAlloc( &p_aout->mixer.output_alloc,
  272.                       ((uint64_t)p_aout->output.i_nb_samples * 1000000)
  273.                         / p_aout->output.output.i_rate,
  274.                       /* This is a bit kludgy, but is actually only used
  275.                        * for the S/PDIF dummy mixer : */
  276.                       p_aout->pp_inputs[i_first_input]->fifo.p_first,
  277.                       p_output_buffer );
  278.     if ( p_output_buffer == NULL )
  279.     {
  280.         aout_unlock_input_fifos( p_aout );
  281.         return -1;
  282.     }
  283.     /* This is again a bit kludgy - for the S/PDIF mixer. */
  284.     if ( p_aout->mixer.output_alloc.i_alloc_type != AOUT_ALLOC_NONE )
  285.     {
  286.         p_output_buffer->i_nb_samples = p_aout->output.i_nb_samples;
  287.         p_output_buffer->i_nb_bytes = p_aout->output.i_nb_samples
  288.                               * p_aout->mixer.mixer.i_bytes_per_frame
  289.                               / p_aout->mixer.mixer.i_frame_length;
  290.     }
  291.     p_output_buffer->start_date = start_date;
  292.     p_output_buffer->end_date = end_date;
  293.     p_aout->mixer.pf_do_work( p_aout, p_output_buffer );
  294.     aout_unlock_input_fifos( p_aout );
  295.     aout_OutputPlay( p_aout, p_output_buffer );
  296.     return 0;
  297. }
  298. /*****************************************************************************
  299.  * aout_MixerRun: entry point for the mixer & post-filters processing
  300.  *****************************************************************************
  301.  * Please note that you must hold the mixer lock.
  302.  *****************************************************************************/
  303. void aout_MixerRun( aout_instance_t * p_aout )
  304. {
  305.     while( MixBuffer( p_aout ) != -1 );
  306. }
  307. /*****************************************************************************
  308.  * aout_MixerMultiplierSet: set p_aout->mixer.f_multiplier
  309.  *****************************************************************************
  310.  * Please note that we assume that you own the mixer lock when entering this
  311.  * function. This function returns -1 on error.
  312.  *****************************************************************************/
  313. int aout_MixerMultiplierSet( aout_instance_t * p_aout, float f_multiplier )
  314. {
  315.     float f_old = p_aout->mixer.f_multiplier;
  316.     bool b_new_mixer = 0;
  317.     if ( !p_aout->mixer.b_error )
  318.     {
  319.         aout_MixerDelete( p_aout );
  320.         b_new_mixer = 1;
  321.     }
  322.     p_aout->mixer.f_multiplier = f_multiplier;
  323.     if ( b_new_mixer && aout_MixerNew( p_aout ) )
  324.     {
  325.         p_aout->mixer.f_multiplier = f_old;
  326.         aout_MixerNew( p_aout );
  327.         return -1;
  328.     }
  329.     return 0;
  330. }
  331. /*****************************************************************************
  332.  * aout_MixerMultiplierGet: get p_aout->mixer.f_multiplier
  333.  *****************************************************************************
  334.  * Please note that we assume that you own the mixer lock when entering this
  335.  * function. This function returns -1 on error.
  336.  *****************************************************************************/
  337. int aout_MixerMultiplierGet( aout_instance_t * p_aout, float * pf_multiplier )
  338. {
  339.     *pf_multiplier = p_aout->mixer.f_multiplier;
  340.     return 0;
  341. }