filters.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:12k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * filters.c : audio output filters management
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2004 VideoLAN
  5.  * $Id: filters.c 8905 2004-10-04 13:34:42Z gbazin $
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                            /* calloc(), malloc(), free() */
  27. #include <string.h>
  28. #include <vlc/vlc.h>
  29. #ifdef HAVE_ALLOCA_H
  30. #   include <alloca.h>
  31. #endif
  32. #include "audio_output.h"
  33. #include "aout_internal.h"
  34. /*****************************************************************************
  35.  * FindFilter: find an audio filter for a specific transformation
  36.  *****************************************************************************/
  37. static aout_filter_t * FindFilter( aout_instance_t * p_aout,
  38.                              const audio_sample_format_t * p_input_format,
  39.                              const audio_sample_format_t * p_output_format )
  40. {
  41.     aout_filter_t * p_filter = vlc_object_create( p_aout,
  42.                                                   sizeof(aout_filter_t) );
  43.     if ( p_filter == NULL ) return NULL;
  44.     vlc_object_attach( p_filter, p_aout );
  45.     memcpy( &p_filter->input, p_input_format, sizeof(audio_sample_format_t) );
  46.     memcpy( &p_filter->output, p_output_format,
  47.             sizeof(audio_sample_format_t) );
  48.     p_filter->p_module = module_Need( p_filter, "audio filter", NULL, 0 );
  49.     if ( p_filter->p_module == NULL )
  50.     {
  51.         vlc_object_detach( p_filter );
  52.         vlc_object_destroy( p_filter );
  53.         return NULL;
  54.     }
  55.     p_filter->b_continuity = VLC_FALSE;
  56.     return p_filter;
  57. }
  58. /*****************************************************************************
  59.  * SplitConversion: split a conversion in two parts
  60.  *****************************************************************************
  61.  * Returns the number of conversions required by the first part - 0 if only
  62.  * one conversion was asked.
  63.  * Beware : p_output_format can be modified during this function if the
  64.  * developer passed SplitConversion( toto, titi, titi, ... ). That is legal.
  65.  * SplitConversion( toto, titi, toto, ... ) isn't.
  66.  *****************************************************************************/
  67. static int SplitConversion( const audio_sample_format_t * p_input_format,
  68.                             const audio_sample_format_t * p_output_format,
  69.                             audio_sample_format_t * p_middle_format )
  70. {
  71.     vlc_bool_t b_format =
  72.              (p_input_format->i_format != p_output_format->i_format);
  73.     vlc_bool_t b_rate = (p_input_format->i_rate != p_output_format->i_rate);
  74.     vlc_bool_t b_channels =
  75.         (p_input_format->i_physical_channels
  76.           != p_output_format->i_physical_channels)
  77.      || (p_input_format->i_original_channels
  78.           != p_output_format->i_original_channels);
  79.     int i_nb_conversions = b_format + b_rate + b_channels;
  80.     if ( i_nb_conversions <= 1 ) return 0;
  81.     memcpy( p_middle_format, p_output_format, sizeof(audio_sample_format_t) );
  82.     if ( i_nb_conversions == 2 )
  83.     {
  84.         if ( !b_format || !b_channels )
  85.         {
  86.             p_middle_format->i_rate = p_input_format->i_rate;
  87.             aout_FormatPrepare( p_middle_format );
  88.             return 1;
  89.         }
  90.         /* !b_rate */
  91.         p_middle_format->i_physical_channels
  92.              = p_input_format->i_physical_channels;
  93.         p_middle_format->i_original_channels
  94.              = p_input_format->i_original_channels;
  95.         aout_FormatPrepare( p_middle_format );
  96.         return 1;
  97.     }
  98.     /* i_nb_conversion == 3 */
  99.     p_middle_format->i_rate = p_input_format->i_rate;
  100.     aout_FormatPrepare( p_middle_format );
  101.     return 2;
  102. }
  103. /*****************************************************************************
  104.  * aout_FiltersCreatePipeline: create a filters pipeline to transform a sample
  105.  *                             format to another
  106.  *****************************************************************************
  107.  * TODO : allow the user to add/remove specific filters
  108.  *****************************************************************************/
  109. int aout_FiltersCreatePipeline( aout_instance_t * p_aout,
  110.                                 aout_filter_t ** pp_filters,
  111.                                 int * pi_nb_filters,
  112.                                 const audio_sample_format_t * p_input_format,
  113.                                 const audio_sample_format_t * p_output_format )
  114. {
  115.     audio_sample_format_t temp_format;
  116.     int i_nb_conversions;
  117.     if ( AOUT_FMTS_IDENTICAL( p_input_format, p_output_format ) )
  118.     {
  119.         msg_Dbg( p_aout, "no need for any filter" );
  120.         *pi_nb_filters = 0;
  121.         return 0;
  122.     }
  123.     aout_FormatsPrint( p_aout, "filter(s)", p_input_format, p_output_format );
  124.     /* Try to find a filter to do the whole conversion. */
  125.     pp_filters[0] = FindFilter( p_aout, p_input_format, p_output_format );
  126.     if ( pp_filters[0] != NULL )
  127.     {
  128.         msg_Dbg( p_aout, "found a filter for the whole conversion" );
  129.         *pi_nb_filters = 1;
  130.         return 0;
  131.     }
  132.     /* We'll have to split the conversion. We always do the downmixing
  133.      * before the resampling, because the audio decoder can probably do it
  134.      * for us. */
  135.     i_nb_conversions = SplitConversion( p_input_format,
  136.                                         p_output_format, &temp_format );
  137.     if ( !i_nb_conversions )
  138.     {
  139.         /* There was only one conversion to do, and we already failed. */
  140.         msg_Err( p_aout, "couldn't find a filter for the conversion" );
  141.         return -1;
  142.     }
  143.     pp_filters[0] = FindFilter( p_aout, p_input_format, &temp_format );
  144.     if ( pp_filters[0] == NULL && i_nb_conversions == 2 )
  145.     {
  146.         /* Try with only one conversion. */
  147.         SplitConversion( p_input_format, &temp_format, &temp_format );
  148.         pp_filters[0] = FindFilter( p_aout, p_input_format, &temp_format );
  149.     }
  150.     if ( pp_filters[0] == NULL )
  151.     {
  152.         msg_Err( p_aout,
  153.               "couldn't find a filter for the first part of the conversion" );
  154.         return -1;
  155.     }
  156.     /* We have the first stage of the conversion. Find a filter for
  157.      * the rest. */
  158.     pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output,
  159.                                 p_output_format );
  160.     if ( pp_filters[1] == NULL )
  161.     {
  162.         /* Try to split the conversion. */
  163.         i_nb_conversions = SplitConversion( &pp_filters[0]->output,
  164.                                            p_output_format, &temp_format );
  165.         if ( !i_nb_conversions )
  166.         {
  167.             vlc_object_detach( pp_filters[0] );
  168.             vlc_object_destroy( pp_filters[0] );
  169.             msg_Err( p_aout,
  170.               "couldn't find a filter for the second part of the conversion" );
  171.         }
  172.         pp_filters[1] = FindFilter( p_aout, &pp_filters[0]->output,
  173.                                     &temp_format );
  174.         pp_filters[2] = FindFilter( p_aout, &temp_format,
  175.                                     p_output_format );
  176.         if ( pp_filters[1] == NULL || pp_filters[2] == NULL )
  177.         {
  178.             vlc_object_detach( pp_filters[0] );
  179.             vlc_object_destroy( pp_filters[0] );
  180.             if ( pp_filters[1] != NULL )
  181.             {
  182.                 vlc_object_detach( pp_filters[1] );
  183.                 vlc_object_destroy( pp_filters[1] );
  184.             }
  185.             if ( pp_filters[2] != NULL )
  186.             {
  187.                 vlc_object_detach( pp_filters[2] );
  188.                 vlc_object_destroy( pp_filters[2] );
  189.             }
  190.             msg_Err( p_aout,
  191.                "couldn't find filters for the second part of the conversion" );
  192.         }
  193.         *pi_nb_filters = 3;
  194.     }
  195.     else
  196.     {
  197.         *pi_nb_filters = 2;
  198.     }
  199.     /* We have enough filters. */
  200.     msg_Dbg( p_aout, "found %d filters for the whole conversion",
  201.              *pi_nb_filters );
  202.     return 0;
  203. }
  204. /*****************************************************************************
  205.  * aout_FiltersDestroyPipeline: deallocate a filters pipeline
  206.  *****************************************************************************/
  207. void aout_FiltersDestroyPipeline( aout_instance_t * p_aout,
  208.                                   aout_filter_t ** pp_filters,
  209.                                   int i_nb_filters )
  210. {
  211.     int i;
  212.     for ( i = 0; i < i_nb_filters; i++ )
  213.     {
  214.         module_Unneed( pp_filters[i], pp_filters[i]->p_module );
  215.         vlc_object_detach( pp_filters[i] );
  216.         vlc_object_destroy( pp_filters[i] );
  217.     }
  218. }
  219. /*****************************************************************************
  220.  * aout_FiltersHintBuffers: fill in aout_alloc_t structures to optimize
  221.  *                          buffer allocations
  222.  *****************************************************************************/
  223. void aout_FiltersHintBuffers( aout_instance_t * p_aout,
  224.                               aout_filter_t ** pp_filters,
  225.                               int i_nb_filters, aout_alloc_t * p_first_alloc )
  226. {
  227.     int i;
  228.     (void)p_aout; /* unused */
  229.     for ( i = i_nb_filters - 1; i >= 0; i-- )
  230.     {
  231.         aout_filter_t * p_filter = pp_filters[i];
  232.         int i_output_size = p_filter->output.i_bytes_per_frame
  233.                              * p_filter->output.i_rate
  234.                              / p_filter->output.i_frame_length;
  235.         int i_input_size = p_filter->input.i_bytes_per_frame
  236.                              * p_filter->input.i_rate
  237.                              / p_filter->input.i_frame_length;
  238.         p_first_alloc->i_bytes_per_sec = __MAX( p_first_alloc->i_bytes_per_sec,
  239.                                                 i_output_size );
  240.         if ( p_filter->b_in_place )
  241.         {
  242.             p_first_alloc->i_bytes_per_sec = __MAX(
  243.                                          p_first_alloc->i_bytes_per_sec,
  244.                                          i_input_size );
  245.             p_filter->output_alloc.i_alloc_type = AOUT_ALLOC_NONE;
  246.         }
  247.         else
  248.         {
  249.             /* We're gonna need a buffer allocation. */
  250.             memcpy( &p_filter->output_alloc, p_first_alloc,
  251.                     sizeof(aout_alloc_t) );
  252.             p_first_alloc->i_alloc_type = AOUT_ALLOC_STACK;
  253.             p_first_alloc->i_bytes_per_sec = i_input_size;
  254.         }
  255.     }
  256. }
  257. /*****************************************************************************
  258.  * aout_FiltersPlay: play a buffer
  259.  *****************************************************************************/
  260. void aout_FiltersPlay( aout_instance_t * p_aout,
  261.                        aout_filter_t ** pp_filters,
  262.                        int i_nb_filters, aout_buffer_t ** pp_input_buffer )
  263. {
  264.     int i;
  265.     for ( i = 0; i < i_nb_filters; i++ )
  266.     {
  267.         aout_filter_t * p_filter = pp_filters[i];
  268.         aout_buffer_t * p_output_buffer;
  269.         /* Resamplers can produce slightly more samples than (i_in_nb *
  270.          * p_filter->output.i_rate / p_filter->input.i_rate) so we need
  271.          * slightly bigger buffers. */
  272.         aout_BufferAlloc( &p_filter->output_alloc,
  273.             ((mtime_t)(*pp_input_buffer)->i_nb_samples + 2)
  274.             * 1000000 / p_filter->input.i_rate,
  275.             *pp_input_buffer, p_output_buffer );
  276.         if ( p_output_buffer == NULL )
  277.         {
  278.             msg_Err( p_aout, "out of memory" );
  279.             return;
  280.         }
  281.         /* Please note that p_output_buffer->i_nb_samples & i_nb_bytes
  282.          * shall be set by the filter plug-in. */
  283.         p_filter->pf_do_work( p_aout, p_filter, *pp_input_buffer,
  284.                               p_output_buffer );
  285.         if ( !p_filter->b_in_place )
  286.         {
  287.             aout_BufferFree( *pp_input_buffer );
  288.             *pp_input_buffer = p_output_buffer;
  289.         }
  290.     }
  291. }