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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * visual.c : Visualisation system
  3.  *****************************************************************************
  4.  * Copyright (C) 2002 VideoLAN
  5.  * $Id: visual.c 8551 2004-08-28 17:36:02Z gbazin $
  6.  *
  7.  * Authors: Cl閙ent Stenac <zorglub@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>                                      /* malloc(), free() */
  27. #include <vlc/vlc.h>
  28. #include <vlc/vout.h>
  29. #include "audio_output.h"
  30. #include "aout_internal.h"
  31. #include "visual.h"
  32. /*****************************************************************************
  33.  * Module descriptor
  34.  *****************************************************************************/
  35. #define ELIST_TEXT N_( "Effects list" )
  36. #define ELIST_LONGTEXT N_( 
  37.       "A list of visual effect, separated by commas.n"  
  38.       "Current effects include: dummy, random, scope, spectrum" )
  39. #define WIDTH_TEXT N_( "Video width" )
  40. #define WIDTH_LONGTEXT N_( 
  41.       "The width of the effects video window, in pixels." )
  42. #define HEIGHT_TEXT N_( "Video height" )
  43. #define HEIGHT_LONGTEXT N_( 
  44.       "The height of the effects video window, in pixels." )
  45. #define NBBANDS_TEXT N_( "Number of bands" )
  46. #define NBBANDS_LONGTEXT N_( 
  47.       "Number of bands used by spectrum analyzer, should be 20 or 80." )
  48. #define SEPAR_TEXT N_( "Band separator" )
  49. #define SEPAR_LONGTEXT N_( 
  50.         "Number of blank pixels between bands.")
  51. #define AMP_TEXT N_( "Amplification" )
  52. #define AMP_LONGTEXT N_( 
  53.         "This is a coefficient that modifies the height of the bands.")
  54. #define PEAKS_TEXT N_( "Enable peaks" )
  55. #define PEAKS_LONGTEXT N_( 
  56.         "Defines whether to draw peaks." )
  57. #define STARS_TEXT N_( "Number of stars" )
  58. #define STARS_LONGTEXT N_( 
  59.         "Defines the number of stars to draw with random effect." )
  60. static int  Open         ( vlc_object_t * );
  61. static void Close        ( vlc_object_t * );
  62. vlc_module_begin();
  63.     set_description( _("visualizer filter") );
  64.     add_string("effect-list", "spectrum", NULL,
  65.             ELIST_TEXT, ELIST_LONGTEXT, VLC_TRUE );
  66.     add_integer("effect-width",VOUT_WIDTH,NULL,
  67.              WIDTH_TEXT, WIDTH_LONGTEXT, VLC_FALSE );
  68.     add_integer("effect-height" , VOUT_HEIGHT , NULL,
  69.              HEIGHT_TEXT, HEIGHT_LONGTEXT, VLC_FALSE );
  70.     add_integer("visual-nbbands", 80, NULL,
  71.              NBBANDS_TEXT, NBBANDS_LONGTEXT, VLC_FALSE );
  72.     add_integer("visual-separ", 1, NULL,
  73.              SEPAR_TEXT, SEPAR_LONGTEXT, VLC_FALSE );
  74.     add_integer("visual-amp", 3, NULL,
  75.              AMP_TEXT, AMP_LONGTEXT, VLC_FALSE );
  76.     add_bool("visual-peaks", VLC_TRUE, NULL,
  77.              PEAKS_TEXT, PEAKS_LONGTEXT, VLC_FALSE );
  78.     add_integer("visual-stars", 200, NULL,
  79.              STARS_TEXT, STARS_LONGTEXT, VLC_FALSE );
  80.     set_capability( "audio filter", 0 );
  81.     set_callbacks( Open, Close );
  82.     add_shortcut( "visualizer");
  83. vlc_module_end();
  84. /*****************************************************************************
  85.  * Local prototypes
  86.  *****************************************************************************/
  87. static void DoWork( aout_instance_t *, aout_filter_t *,
  88.                     aout_buffer_t *, aout_buffer_t * );
  89. static int FilterCallback( vlc_object_t *, char const *,
  90.                            vlc_value_t, vlc_value_t, void * );
  91. static struct
  92. {
  93.     char *psz_name;
  94.     int  (*pf_run)( visual_effect_t *, aout_instance_t *,
  95.                     aout_buffer_t *, picture_t *);
  96. } pf_effect_run[]=
  97. {
  98.     { "scope",      scope_Run },
  99.     { "spectrum",   spectrum_Run },
  100.     { "random",     random_Run},
  101.     { "dummy",      dummy_Run},
  102.     { NULL,         dummy_Run}
  103. };
  104. /*****************************************************************************
  105.  * Open: open the visualizer
  106.  *****************************************************************************/
  107. static int Open( vlc_object_t *p_this )
  108. {
  109.     aout_filter_t     *p_filter = (aout_filter_t *)p_this;
  110.     aout_filter_sys_t *p_sys;
  111.     vlc_value_t        val;
  112.     char *psz_effects, *psz_parser;
  113.     if( ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2') &&
  114.           p_filter->input.i_format != VLC_FOURCC('f','i','3','2') ) )
  115.     {
  116.         return VLC_EGENERIC;
  117.     }
  118.     p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) );
  119.     if( p_sys == NULL )
  120.     {
  121.         msg_Err( p_filter, "out of memory" );
  122.         return VLC_EGENERIC;
  123.     }
  124.     p_sys->i_height = config_GetInt( p_filter , "effect-height");
  125.     p_sys->i_width  = config_GetInt( p_filter , "effect-width");
  126.     if( p_sys->i_height < 20 ) p_sys->i_height =  20;
  127.     if( p_sys->i_width  < 20 ) p_sys->i_width  =  20;
  128.     if( (p_sys->i_height % 2 ) != 0 ) p_sys->i_height--;
  129.     if( (p_sys->i_width % 2 )  != 0 ) p_sys->i_width--;
  130.     p_sys->i_effect = 0;
  131.     p_sys->effect   = NULL;
  132.     /* Parse the effect list */
  133.     var_Create( p_filter, "effect-list", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
  134.     var_Get( p_filter, "effect-list", &val);
  135.     psz_parser = psz_effects = strdup( val.psz_string );
  136.     free( val.psz_string );
  137.     msg_Dbg( p_filter , "Building list of effects" );
  138.     
  139.     var_AddCallback( p_filter, "effect-list", FilterCallback, NULL );
  140.     while( psz_parser && *psz_parser != '' )
  141.     {
  142.         visual_effect_t *p_effect;
  143.         int  i;
  144.         p_effect = malloc( sizeof( visual_effect_t ) );
  145.         p_effect->i_width = p_sys->i_width;
  146.         p_effect->i_height= p_sys->i_height;
  147.         p_effect->i_nb_chans = aout_FormatNbChannels( &p_filter->input);
  148.         p_effect->psz_args = NULL;
  149.         p_effect->p_data = NULL;
  150.         p_effect->pf_run = NULL;
  151.         p_effect->psz_name = NULL;
  152.         for( i = 0; pf_effect_run[i].psz_name != NULL; i++ )
  153.         {
  154.             if( !strncasecmp( psz_parser,
  155.                               pf_effect_run[i].psz_name,
  156.                               strlen( pf_effect_run[i].psz_name ) ) )
  157.             {
  158.                 p_effect->pf_run = pf_effect_run[i].pf_run;
  159.                 p_effect->psz_name = strdup( pf_effect_run[i].psz_name );
  160.                 break;
  161.             }
  162.         }
  163.         if( p_effect->psz_name )
  164.         {
  165.             psz_parser += strlen( p_effect->psz_name );
  166.             if( *psz_parser == '{' )
  167.             {
  168.                 char *psz_eoa;
  169.                 psz_parser++;
  170.                 if( ( psz_eoa = strchr( psz_parser, '}') ) == NULL )
  171.                 {
  172.                    msg_Err( p_filter, "Unable to parse effect list. Aborting");
  173.                    break;
  174.                 }
  175.                 p_effect->psz_args =
  176.                     strndup( psz_parser, psz_eoa - psz_parser);
  177.             }
  178.             TAB_APPEND( p_sys->i_effect, p_sys->effect, p_effect );
  179.         }
  180.         else
  181.         {
  182.             msg_Err( p_filter, "unknown visual effect: %s", psz_parser );
  183.             free( p_effect );
  184.         }
  185.         if( strchr( psz_parser, ',' ) )
  186.         {
  187.             psz_parser = strchr( psz_parser, ',' ) + 1;
  188.         }
  189.         else if( strchr( psz_parser, ':' ) )
  190.         {
  191.             psz_parser = strchr( psz_parser, ':' ) + 1;
  192.         }
  193.         else
  194.         {
  195.             break;
  196.         }
  197.     }
  198.     if( psz_effects )
  199.     {
  200.         free( psz_effects );
  201.     }
  202.     if( !p_sys->i_effect )
  203.     {
  204.         msg_Err( p_filter, "no effects found" );
  205.         free( p_sys );
  206.         return VLC_EGENERIC;
  207.     }
  208.     /* Open the video output */
  209.     p_sys->p_vout =
  210.          vout_Request( p_filter, NULL,
  211.                        p_sys->i_width, p_sys->i_height,
  212.                        VLC_FOURCC('I','4','2','0'),
  213.                        VOUT_ASPECT_FACTOR * p_sys->i_width/p_sys->i_height );
  214.     if( p_sys->p_vout == NULL )
  215.     {
  216.         msg_Err( p_filter, "no suitable vout module" );
  217.         free( p_sys );
  218.         return VLC_EGENERIC;
  219.     }
  220.     p_filter->pf_do_work = DoWork;
  221.     p_filter->b_in_place= 1;
  222.     msg_Dbg( p_filter,"Visualizer initialized");
  223.     return VLC_SUCCESS;
  224. }
  225. /*****************************************************************************
  226.  * DoWork: convert a buffer
  227.  *****************************************************************************
  228.  * Audio part pasted from trivial.c
  229.  ****************************************************************************/
  230. static void DoWork( aout_instance_t *p_aout, aout_filter_t *p_filter,
  231.                     aout_buffer_t *p_in_buf, aout_buffer_t *p_out_buf )
  232. {
  233.     aout_filter_sys_t *p_sys = p_filter->p_sys;
  234.     picture_t *p_outpic;
  235.     int i;
  236.     p_out_buf->i_nb_samples = p_in_buf->i_nb_samples;
  237.     p_out_buf->i_nb_bytes = p_in_buf->i_nb_bytes *
  238.                             aout_FormatNbChannels( &p_filter->output ) /
  239.                             aout_FormatNbChannels( &p_filter->input );
  240.     /* First, get a new picture */
  241.     while( ( p_outpic = vout_CreatePicture( p_sys->p_vout, 0, 0, 3 ) ) == NULL)
  242.     {
  243.         if( p_aout->b_die )
  244.         {
  245.             return;
  246.         }
  247.         msleep( VOUT_OUTMEM_SLEEP );
  248.     }
  249.     /* Blank the picture */
  250.     for( i = 0 ; i < p_outpic->i_planes ; i++ )
  251.     {
  252.         memset( p_outpic->p[i].p_pixels, i > 0 ? 0x80 : 0x00,
  253.                 p_outpic->p[i].i_visible_lines * p_outpic->p[i].i_pitch );
  254.     }
  255.     /* We can now call our visualization effects */
  256.     for( i = 0; i < p_sys->i_effect; i++ )
  257.     {
  258. #define p_effect p_sys->effect[i]
  259.         if( p_effect->pf_run )
  260.         {
  261.             p_effect->pf_run( p_effect, p_aout, p_out_buf, p_outpic );
  262.         }
  263. #undef p_effect
  264.     }
  265.     vout_DatePicture( p_sys->p_vout, p_outpic,
  266.                       ( p_in_buf->start_date + p_in_buf->end_date ) / 2 );
  267.     vout_DisplayPicture( p_sys->p_vout, p_outpic );
  268. }
  269. /*****************************************************************************
  270.  * Close: close the plugin
  271.  *****************************************************************************/
  272. static void Close( vlc_object_t *p_this )
  273. {
  274.     aout_filter_t * p_filter = (aout_filter_t *)p_this;
  275.     aout_filter_sys_t *p_sys = p_filter->p_sys;
  276.     int i;
  277.     if( p_filter->p_sys->p_vout )
  278.     {
  279.         vout_Request( p_filter, p_filter->p_sys->p_vout, 0, 0, 0, 0 );
  280.     }
  281.     /* Free the list */
  282.     for( i = 0; i < p_sys->i_effect; i++ )
  283.     {
  284. #define p_effect p_sys->effect[i]
  285.         if( p_effect->psz_name )
  286.         {
  287.             free( p_effect->psz_name );
  288.         }
  289.         if( p_effect->psz_args )
  290.         {
  291.             free( p_effect->psz_args );
  292.         }
  293.         free( p_effect );
  294. #undef p_effect
  295.     }
  296.     if( p_sys->effect )
  297.     {
  298.         free( p_sys->effect );
  299.     }
  300.     free( p_filter->p_sys );
  301. }
  302. /*****************************************************************************
  303.  * FilterCallback: called when changing the deinterlace method on the fly.
  304.  *****************************************************************************/
  305. static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd,
  306.                            vlc_value_t oldval, vlc_value_t newval,
  307.                            void *p_data )
  308. {
  309.     aout_filter_t     *p_filter = (aout_filter_t *)p_this;
  310.     /* restart this baby */
  311.     msg_Dbg( p_filter, "We should restart the visual filter" );
  312.     return VLC_SUCCESS;
  313. }