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

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * output.c : internal management of output streams for the audio output
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2004 the VideoLAN team
  5.  * $Id: 8728427586d2385eac3322f19d51537b19a0ca89 $
  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 <vlc_common.h>
  30. #include <vlc_aout.h>
  31. #include "aout_internal.h"
  32. /*****************************************************************************
  33.  * aout_OutputNew : allocate a new output and rework the filter pipeline
  34.  *****************************************************************************
  35.  * This function is entered with the mixer lock.
  36.  *****************************************************************************/
  37. int aout_OutputNew( aout_instance_t * p_aout,
  38.                     audio_sample_format_t * p_format )
  39. {
  40.     /* Retrieve user defaults. */
  41.     int i_rate = config_GetInt( p_aout, "aout-rate" );
  42.     vlc_value_t val, text;
  43.     /* kludge to avoid a fpu error when rate is 0... */
  44.     if( i_rate == 0 ) i_rate = -1;
  45.     memcpy( &p_aout->output.output, p_format, sizeof(audio_sample_format_t) );
  46.     if ( i_rate != -1 )
  47.         p_aout->output.output.i_rate = i_rate;
  48.     aout_FormatPrepare( &p_aout->output.output );
  49.     aout_lock_output_fifo( p_aout );
  50.     /* Find the best output plug-in. */
  51.     p_aout->output.p_module = module_need( p_aout, "audio output", "$aout", false );
  52.     if ( p_aout->output.p_module == NULL )
  53.     {
  54.         msg_Err( p_aout, "no suitable audio output module" );
  55.         aout_unlock_output_fifo( p_aout );
  56.         return -1;
  57.     }
  58.     if ( var_Type( p_aout, "audio-channels" ) ==
  59.              (VLC_VAR_INTEGER | VLC_VAR_HASCHOICE) )
  60.     {
  61.         /* The user may have selected a different channels configuration. */
  62.         var_Get( p_aout, "audio-channels", &val );
  63.         if ( val.i_int == AOUT_VAR_CHAN_RSTEREO )
  64.         {
  65.             p_aout->output.output.i_original_channels |=
  66.                                         AOUT_CHAN_REVERSESTEREO;
  67.         }
  68.         else if ( val.i_int == AOUT_VAR_CHAN_STEREO )
  69.         {
  70.             p_aout->output.output.i_original_channels =
  71.                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
  72.         }
  73.         else if ( val.i_int == AOUT_VAR_CHAN_LEFT )
  74.         {
  75.             p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT;
  76.         }
  77.         else if ( val.i_int == AOUT_VAR_CHAN_RIGHT )
  78.         {
  79.             p_aout->output.output.i_original_channels = AOUT_CHAN_RIGHT;
  80.         }
  81.         else if ( val.i_int == AOUT_VAR_CHAN_DOLBYS )
  82.         {
  83.             p_aout->output.output.i_original_channels
  84.                 = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_DOLBYSTEREO;
  85.         }
  86.     }
  87.     else if ( p_aout->output.output.i_physical_channels == AOUT_CHAN_CENTER
  88.               && (p_aout->output.output.i_original_channels
  89.                    & AOUT_CHAN_PHYSMASK) == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) )
  90.     {
  91.         /* Mono - create the audio-channels variable. */
  92.         var_Create( p_aout, "audio-channels",
  93.                     VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
  94.         text.psz_string = _("Audio Channels");
  95.         var_Change( p_aout, "audio-channels", VLC_VAR_SETTEXT, &text, NULL );
  96.         val.i_int = AOUT_VAR_CHAN_STEREO; text.psz_string = _("Stereo");
  97.         var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
  98.         val.i_int = AOUT_VAR_CHAN_LEFT; text.psz_string = _("Left");
  99.         var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
  100.         val.i_int = AOUT_VAR_CHAN_RIGHT; text.psz_string = _("Right");
  101.         var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
  102.         if ( p_aout->output.output.i_original_channels & AOUT_CHAN_DUALMONO )
  103.         {
  104.             /* Go directly to the left channel. */
  105.             p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT;
  106.             val.i_int = AOUT_VAR_CHAN_LEFT;
  107.             var_Set( p_aout, "audio-channels", val );
  108.         }
  109.         var_AddCallback( p_aout, "audio-channels", aout_ChannelsRestart,
  110.                          NULL );
  111.     }
  112.     else if ( p_aout->output.output.i_physical_channels ==
  113.                (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)
  114.                 && (p_aout->output.output.i_original_channels &
  115.                      (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT)) )
  116.     {
  117.         /* Stereo - create the audio-channels variable. */
  118.         var_Create( p_aout, "audio-channels",
  119.                     VLC_VAR_INTEGER | VLC_VAR_HASCHOICE );
  120.         text.psz_string = _("Audio Channels");
  121.         var_Change( p_aout, "audio-channels", VLC_VAR_SETTEXT, &text, NULL );
  122.         if ( p_aout->output.output.i_original_channels & AOUT_CHAN_DOLBYSTEREO )
  123.         {
  124.             val.i_int = AOUT_VAR_CHAN_DOLBYS;
  125.             text.psz_string = _("Dolby Surround");
  126.         }
  127.         else
  128.         {
  129.             val.i_int = AOUT_VAR_CHAN_STEREO;
  130.             text.psz_string = _("Stereo");
  131.         }
  132.         var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
  133.         val.i_int = AOUT_VAR_CHAN_LEFT; text.psz_string = _("Left");
  134.         var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
  135.         val.i_int = AOUT_VAR_CHAN_RIGHT; text.psz_string = _("Right");
  136.         var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
  137.         val.i_int = AOUT_VAR_CHAN_RSTEREO; text.psz_string=_("Reverse stereo");
  138.         var_Change( p_aout, "audio-channels", VLC_VAR_ADDCHOICE, &val, &text );
  139.         if ( p_aout->output.output.i_original_channels & AOUT_CHAN_DUALMONO )
  140.         {
  141.             /* Go directly to the left channel. */
  142.             p_aout->output.output.i_original_channels = AOUT_CHAN_LEFT;
  143.             val.i_int = AOUT_VAR_CHAN_LEFT;
  144.             var_Set( p_aout, "audio-channels", val );
  145.         }
  146.         var_AddCallback( p_aout, "audio-channels", aout_ChannelsRestart,
  147.                          NULL );
  148.     }
  149.     val.b_bool = true;
  150.     var_Set( p_aout, "intf-change", val );
  151.     aout_FormatPrepare( &p_aout->output.output );
  152.     /* Prepare FIFO. */
  153.     aout_FifoInit( p_aout, &p_aout->output.fifo,
  154.                    p_aout->output.output.i_rate );
  155.     aout_unlock_output_fifo( p_aout );
  156.     aout_FormatPrint( p_aout, "output", &p_aout->output.output );
  157.     /* Calculate the resulting mixer output format. */
  158.     memcpy( &p_aout->mixer.mixer, &p_aout->output.output,
  159.             sizeof(audio_sample_format_t) );
  160.     if ( !AOUT_FMT_NON_LINEAR(&p_aout->output.output) )
  161.     {
  162.         /* Non-S/PDIF mixer only deals with float32 or fixed32. */
  163.         p_aout->mixer.mixer.i_format
  164.                      = (vlc_CPU() & CPU_CAPABILITY_FPU) ?
  165.                         VLC_FOURCC('f','l','3','2') :
  166.                         VLC_FOURCC('f','i','3','2');
  167.         aout_FormatPrepare( &p_aout->mixer.mixer );
  168.     }
  169.     else
  170.     {
  171.         p_aout->mixer.mixer.i_format = p_format->i_format;
  172.     }
  173.     aout_FormatPrint( p_aout, "mixer", &p_aout->mixer.mixer );
  174.     /* Create filters. */
  175.     p_aout->output.i_nb_filters = 0;
  176.     if ( aout_FiltersCreatePipeline( p_aout, p_aout->output.pp_filters,
  177.                                      &p_aout->output.i_nb_filters,
  178.                                      &p_aout->mixer.mixer,
  179.                                      &p_aout->output.output ) < 0 )
  180.     {
  181.         msg_Err( p_aout, "couldn't create audio output pipeline" );
  182.         module_unneed( p_aout, p_aout->output.p_module );
  183.         return -1;
  184.     }
  185.     /* Prepare hints for the buffer allocator. */
  186.     p_aout->mixer.output_alloc.i_alloc_type = AOUT_ALLOC_HEAP;
  187.     p_aout->mixer.output_alloc.i_bytes_per_sec
  188.                         = p_aout->mixer.mixer.i_bytes_per_frame
  189.                            * p_aout->mixer.mixer.i_rate
  190.                            / p_aout->mixer.mixer.i_frame_length;
  191.     aout_FiltersHintBuffers( p_aout, p_aout->output.pp_filters,
  192.                              p_aout->output.i_nb_filters,
  193.                              &p_aout->mixer.output_alloc );
  194.     p_aout->output.b_error = 0;
  195.     return 0;
  196. }
  197. /*****************************************************************************
  198.  * aout_OutputDelete : delete the output
  199.  *****************************************************************************
  200.  * This function is entered with the mixer lock.
  201.  *****************************************************************************/
  202. void aout_OutputDelete( aout_instance_t * p_aout )
  203. {
  204.     if ( p_aout->output.b_error )
  205.     {
  206.         return;
  207.     }
  208.     module_unneed( p_aout, p_aout->output.p_module );
  209.     aout_FiltersDestroyPipeline( p_aout, p_aout->output.pp_filters,
  210.                                  p_aout->output.i_nb_filters );
  211.     aout_lock_output_fifo( p_aout );
  212.     aout_FifoDestroy( p_aout, &p_aout->output.fifo );
  213.     aout_unlock_output_fifo( p_aout );
  214.     p_aout->output.b_error = true;
  215. }
  216. /*****************************************************************************
  217.  * aout_OutputPlay : play a buffer
  218.  *****************************************************************************
  219.  * This function is entered with the mixer lock.
  220.  *****************************************************************************/
  221. void aout_OutputPlay( aout_instance_t * p_aout, aout_buffer_t * p_buffer )
  222. {
  223.     aout_FiltersPlay( p_aout, p_aout->output.pp_filters,
  224.                       p_aout->output.i_nb_filters,
  225.                       &p_buffer );
  226.     if( p_buffer->i_nb_bytes == 0 )
  227.     {
  228.         aout_BufferFree( p_buffer );
  229.         return;
  230.     }
  231.     aout_lock_output_fifo( p_aout );
  232.     aout_FifoPush( p_aout, &p_aout->output.fifo, p_buffer );
  233.     p_aout->output.pf_play( p_aout );
  234.     aout_unlock_output_fifo( p_aout );
  235. }
  236. /*****************************************************************************
  237.  * aout_OutputNextBuffer : give the audio output plug-in the right buffer
  238.  *****************************************************************************
  239.  * If b_can_sleek is 1, the aout core functions won't try to resample
  240.  * new buffers to catch up - that is we suppose that the output plug-in can
  241.  * compensate it by itself. S/PDIF outputs should always set b_can_sleek = 1.
  242.  * This function is entered with no lock at all :-).
  243.  *****************************************************************************/
  244. aout_buffer_t * aout_OutputNextBuffer( aout_instance_t * p_aout,
  245.                                        mtime_t start_date,
  246.                                        bool b_can_sleek )
  247. {
  248.     aout_buffer_t * p_buffer;
  249.     aout_lock_output_fifo( p_aout );
  250.     p_buffer = p_aout->output.fifo.p_first;
  251.     /* Drop the audio sample if the audio output is really late.
  252.      * In the case of b_can_sleek, we don't use a resampler so we need to be
  253.      * a lot more severe. */
  254.     while ( p_buffer && p_buffer->start_date <
  255.             (b_can_sleek ? start_date : mdate()) - AOUT_PTS_TOLERANCE )
  256.     {
  257.         msg_Dbg( p_aout, "audio output is too slow (%"PRId64"), "
  258.                  "trashing %"PRId64"us", mdate() - p_buffer->start_date,
  259.                  p_buffer->end_date - p_buffer->start_date );
  260.         p_buffer = p_buffer->p_next;
  261.         aout_BufferFree( p_aout->output.fifo.p_first );
  262.         p_aout->output.fifo.p_first = p_buffer;
  263.     }
  264.     if ( p_buffer == NULL )
  265.     {
  266.         p_aout->output.fifo.pp_last = &p_aout->output.fifo.p_first;
  267. #if 0 /* This is bad because the audio output might just be trying to fill
  268.        * in its internal buffers. And anyway, it's up to the audio output
  269.        * to deal with this kind of starvation. */
  270.         /* Set date to 0, to allow the mixer to send a new buffer ASAP */
  271.         aout_FifoSet( p_aout, &p_aout->output.fifo, 0 );
  272.         if ( !p_aout->output.b_starving )
  273.             msg_Dbg( p_aout,
  274.                  "audio output is starving (no input), playing silence" );
  275.         p_aout->output.b_starving = 1;
  276. #endif
  277.         aout_unlock_output_fifo( p_aout );
  278.         return NULL;
  279.     }
  280.     /* Here we suppose that all buffers have the same duration - this is
  281.      * generally true, and anyway if it's wrong it won't be a disaster.
  282.      */
  283.     if ( p_buffer->start_date > start_date
  284.                          + (p_buffer->end_date - p_buffer->start_date) )
  285.     /*
  286.      *                   + AOUT_PTS_TOLERANCE )
  287.      * There is no reason to want that, it just worsen the scheduling of
  288.      * an audio sample after an output starvation (ie. on start or on resume)
  289.      * --Gibalou
  290.      */
  291.     {
  292.         const mtime_t i_delta = p_buffer->start_date - start_date;
  293.         aout_unlock_output_fifo( p_aout );
  294.         if ( !p_aout->output.b_starving )
  295.             msg_Dbg( p_aout, "audio output is starving (%"PRId64"), "
  296.                      "playing silence", i_delta );
  297.         p_aout->output.b_starving = 1;
  298.         return NULL;
  299.     }
  300.     p_aout->output.b_starving = 0;
  301.     p_aout->output.fifo.p_first = p_buffer->p_next;
  302.     if ( p_buffer->p_next == NULL )
  303.     {
  304.         p_aout->output.fifo.pp_last = &p_aout->output.fifo.p_first;
  305.     }
  306.     if ( !b_can_sleek &&
  307.           ( (p_buffer->start_date - start_date > AOUT_PTS_TOLERANCE)
  308.              || (start_date - p_buffer->start_date > AOUT_PTS_TOLERANCE) ) )
  309.     {
  310.         /* Try to compensate the drift by doing some resampling. */
  311.         int i;
  312.         mtime_t difference = start_date - p_buffer->start_date;
  313.         msg_Warn( p_aout, "output date isn't PTS date, requesting "
  314.                   "resampling (%"PRId64")", difference );
  315.         aout_FifoMoveDates( p_aout, &p_aout->output.fifo, difference );
  316.         aout_unlock_output_fifo( p_aout );
  317.         aout_lock_input_fifos( p_aout );
  318.         for ( i = 0; i < p_aout->i_nb_inputs; i++ )
  319.         {
  320.             aout_fifo_t * p_fifo = &p_aout->pp_inputs[i]->fifo;
  321.             aout_FifoMoveDates( p_aout, p_fifo, difference );
  322.         }
  323.         aout_unlock_input_fifos( p_aout );
  324.     }
  325.     else
  326.         aout_unlock_output_fifo( p_aout );
  327.     return p_buffer;
  328. }