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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * adjust.c : Contrast/Hue/Saturation/Brightness video plugin for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2000, 2001, 2002, 2003 VideoLAN
  5.  * $Id: adjust.c 8551 2004-08-28 17:36:02Z gbazin $
  6.  *
  7.  * Authors: Simon Latapie <garf@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 <errno.h>
  27. #include <stdlib.h>                                      /* malloc(), free() */
  28. #include <string.h>
  29. #include <math.h>
  30. #include <vlc/vlc.h>
  31. #include <vlc/vout.h>
  32. #include "filter_common.h"
  33. #ifndef M_PI
  34. #   define M_PI 3.14159265358979323846
  35. #endif
  36. #define eight_times( x )    x x x x x x x x
  37. /*****************************************************************************
  38.  * Local prototypes
  39.  *****************************************************************************/
  40. static int  Create    ( vlc_object_t * );
  41. static void Destroy   ( vlc_object_t * );
  42. static int  Init      ( vout_thread_t * );
  43. static void End       ( vout_thread_t * );
  44. static void Render    ( vout_thread_t *, picture_t * );
  45. static int  SendEvents( vlc_object_t *, char const *,
  46.                         vlc_value_t, vlc_value_t, void * );
  47. /*****************************************************************************
  48.  * Module descriptor
  49.  *****************************************************************************/
  50. #define CONT_TEXT N_("Image contrast (0-2)")
  51. #define CONT_LONGTEXT N_("Set the image contrast, between 0 and 2. Defaults to 1")
  52. #define HUE_TEXT N_("Image hue (0-360)")
  53. #define HUE_LONGTEXT N_("Set the image hue, between 0 and 360. Defaults to 0")
  54. #define SAT_TEXT N_("Image saturation (0-3)")
  55. #define SAT_LONGTEXT N_("Set the image saturation, between 0 and 3. Defaults to 1")
  56. #define LUM_TEXT N_("Image brightness (0-2)")
  57. #define LUM_LONGTEXT N_("Set the image brightness, between 0 and 2. Defaults to 1")
  58. #define GAMMA_TEXT N_("Image gamma (0-10)")
  59. #define GAMMA_LONGTEXT N_("Set the image gamma, between 0.01 and 10. Defaults to 1")
  60. vlc_module_begin();
  61.     set_description( _("Image properties filter") );
  62.     set_capability( "video filter", 0 );
  63.     add_float_with_range( "contrast", 1.0, 0.0, 2.0, NULL, CONT_TEXT, CONT_LONGTEXT, VLC_FALSE );
  64.     add_float_with_range( "brightness", 1.0, 0.0, 2.0, NULL, LUM_TEXT, LUM_LONGTEXT, VLC_FALSE );
  65.     add_integer_with_range( "hue", 0, 0, 360, NULL, HUE_TEXT, HUE_LONGTEXT, VLC_FALSE );
  66.     add_float_with_range( "saturation", 1.0, 0.0, 3.0, NULL, SAT_TEXT, SAT_LONGTEXT, VLC_FALSE );
  67.     add_float_with_range( "gamma", 1.0, 0.01, 10.0, NULL, GAMMA_TEXT, GAMMA_LONGTEXT, VLC_FALSE );
  68.     add_shortcut( "adjust" );
  69.     set_callbacks( Create, Destroy );
  70. vlc_module_end();
  71. /*****************************************************************************
  72.  * vout_sys_t: adjust video output method descriptor
  73.  *****************************************************************************
  74.  * This structure is part of the video output thread descriptor.
  75.  * It describes the adjust specific properties of an output thread.
  76.  *****************************************************************************/
  77. struct vout_sys_t
  78. {
  79.     vout_thread_t *p_vout;
  80. };
  81. inline static int32_t clip( int32_t a )
  82. {
  83.     return (a > 255) ? 255 : (a < 0) ? 0 : a;
  84. }
  85. /*****************************************************************************
  86.  * Control: control facility for the vout (forwards to child vout)
  87.  *****************************************************************************/
  88. static int Control( vout_thread_t *p_vout, int i_query, va_list args )
  89. {
  90.     return vout_vaControl( p_vout->p_sys->p_vout, i_query, args );
  91. }
  92. /*****************************************************************************
  93.  * Create: allocates adjust video thread output method
  94.  *****************************************************************************
  95.  * This function allocates and initializes a adjust vout method.
  96.  *****************************************************************************/
  97. static int Create( vlc_object_t *p_this )
  98. {
  99.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  100.     /* Allocate structure */
  101.     p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
  102.     if( p_vout->p_sys == NULL )
  103.     {
  104.         msg_Err( p_vout, "out of memory" );
  105.         return VLC_ENOMEM;
  106.     }
  107.     p_vout->pf_init = Init;
  108.     p_vout->pf_end = End;
  109.     p_vout->pf_manage = NULL;
  110.     p_vout->pf_render = Render;
  111.     p_vout->pf_display = NULL;
  112.     p_vout->pf_control = Control;
  113.     
  114.     var_Create( p_vout, "contrast", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
  115.     var_Create( p_vout, "brightness", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
  116.     var_Create( p_vout, "hue", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
  117.     var_Create( p_vout, "saturation", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
  118.     var_Create( p_vout, "gamma", VLC_VAR_FLOAT | VLC_VAR_DOINHERIT );
  119.     return VLC_SUCCESS;
  120. }
  121. /*****************************************************************************
  122.  * Init: initialize adjust video thread output method
  123.  *****************************************************************************/
  124. static int Init( vout_thread_t *p_vout )
  125. {
  126.     int i_index;
  127.     picture_t *p_pic;
  128.     I_OUTPUTPICTURES = 0;
  129.     /* Initialize the output structure */
  130.     p_vout->output.i_chroma = p_vout->render.i_chroma;
  131.     p_vout->output.i_width  = p_vout->render.i_width;
  132.     p_vout->output.i_height = p_vout->render.i_height;
  133.     p_vout->output.i_aspect = p_vout->render.i_aspect;
  134.     /* Try to open the real video output */
  135.     msg_Dbg( p_vout, "spawning the real video output" );
  136.     p_vout->p_sys->p_vout = vout_Create( p_vout,
  137.                      p_vout->render.i_width, p_vout->render.i_height,
  138.                      p_vout->render.i_chroma, p_vout->render.i_aspect );
  139.     /* Everything failed */
  140.     if( p_vout->p_sys->p_vout == NULL )
  141.     {
  142.         msg_Err( p_vout, "can't open vout, aborting" );
  143.         return VLC_EGENERIC;
  144.     }
  145.     ALLOCATE_DIRECTBUFFERS( VOUT_MAX_PICTURES );
  146.     ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
  147.     ADD_PARENT_CALLBACKS( SendEventsToChild );
  148.     return VLC_SUCCESS;
  149. }
  150. /*****************************************************************************
  151.  * End: terminate adjust video thread output method
  152.  *****************************************************************************/
  153. static void End( vout_thread_t *p_vout )
  154. {
  155.     int i_index;
  156.     /* Free the fake output buffers we allocated */
  157.     for( i_index = I_OUTPUTPICTURES ; i_index ; )
  158.     {
  159.         i_index--;
  160.         free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
  161.     }
  162. }
  163. /*****************************************************************************
  164.  * Destroy: destroy adjust video thread output method
  165.  *****************************************************************************
  166.  * Terminate an output method created by adjustCreateOutputMethod
  167.  *****************************************************************************/
  168. static void Destroy( vlc_object_t *p_this )
  169. {
  170.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  171.     if( p_vout->p_sys->p_vout )
  172.     {
  173.         DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents );
  174.         vlc_object_detach( p_vout->p_sys->p_vout );
  175.         vout_Destroy( p_vout->p_sys->p_vout );
  176.     }
  177.     DEL_PARENT_CALLBACKS( SendEventsToChild );
  178.     free( p_vout->p_sys );
  179. }
  180. /*****************************************************************************
  181.  * Render: displays previously rendered output
  182.  *****************************************************************************
  183.  * This function send the currently rendered image to adjust modified image,
  184.  * waits until it is displayed and switch the two rendering buffers, preparing
  185.  * next frame.
  186.  *****************************************************************************/
  187. static void Render( vout_thread_t *p_vout, picture_t *p_pic )
  188. {
  189.     int pi_luma[256];
  190.     int pi_gamma[256];
  191.     picture_t *p_outpic;
  192.     uint8_t *p_in, *p_in_v, *p_in_end, *p_line_end;
  193.     uint8_t *p_out, *p_out_v;
  194.     double  f_hue;
  195.     double  f_gamma;
  196.     int32_t i_cont, i_lum;
  197.     int i_sat, i_sin, i_cos, i_x, i_y;
  198.     int i;
  199.     vlc_value_t val;
  200.     /* This is a new frame. Get a structure from the video_output. */
  201.     while( ( p_outpic = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) )
  202.               == NULL )
  203.     {
  204.         if( p_vout->b_die || p_vout->b_error )
  205.         {
  206.             return;
  207.         }
  208.         msleep( VOUT_OUTMEM_SLEEP );
  209.     }
  210.     vout_DatePicture( p_vout->p_sys->p_vout, p_outpic, p_pic->date );
  211.     vout_LinkPicture( p_vout->p_sys->p_vout, p_outpic );
  212.     /* Getvariables */
  213.     var_Get( p_vout, "contrast", &val );
  214.     i_cont = (int) ( val.f_float * 255 );
  215.     var_Get( p_vout, "brightness", &val );
  216.     i_lum = (int) (( val.f_float - 1.0 ) * 255 );
  217.     var_Get( p_vout, "hue", &val );
  218.     f_hue = (float) ( val.i_int * M_PI / 180 );
  219.     var_Get( p_vout, "saturation", &val );
  220.     i_sat = (int) (val.f_float * 256 );
  221.     var_Get( p_vout, "gamma", &val );
  222.     f_gamma = 1.0 / val.f_float;
  223.     /* Contrast is a fast but kludged function, so I put this gap to be
  224.      * cleaner :) */
  225.     i_lum += 128 - i_cont / 2;
  226.     /* Fill the gamma lookup table */
  227.     for( i = 0 ; i < 256 ; i++ )
  228.     {
  229.       pi_gamma[ i ] = clip( pow(i / 255.0, f_gamma) * 255.0);
  230.     }
  231.     /* Fill the luma lookup table */
  232.     for( i = 0 ; i < 256 ; i++ )
  233.     {
  234.         pi_luma[ i ] = pi_gamma[clip( i_lum + i_cont * i / 256)];
  235.     }
  236.     /*
  237.      * Do the Y plane
  238.      */
  239.     p_in = p_pic->p[0].p_pixels;
  240.     p_in_end = p_in + p_pic->p[0].i_visible_lines * p_pic->p[0].i_pitch - 8;
  241.     p_out = p_outpic->p[0].p_pixels;
  242.     for( ; p_in < p_in_end ; )
  243.     {
  244.         p_line_end = p_in + p_pic->p[0].i_visible_pitch - 8;
  245.         for( ; p_in < p_line_end ; )
  246.         {
  247.             /* Do 8 pixels at a time */
  248.             *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
  249.             *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
  250.             *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
  251.             *p_out++ = pi_luma[ *p_in++ ]; *p_out++ = pi_luma[ *p_in++ ];
  252.         }
  253.         p_line_end += 8;
  254.         for( ; p_in < p_line_end ; )
  255.         {
  256.             *p_out++ = pi_luma[ *p_in++ ];
  257.         }
  258.         p_in += p_pic->p[0].i_pitch - p_pic->p[0].i_visible_pitch;
  259.         p_out += p_outpic->p[0].i_pitch - p_outpic->p[0].i_visible_pitch;
  260.     }
  261.     /*
  262.      * Do the U and V planes
  263.      */
  264.     p_in = p_pic->p[1].p_pixels;
  265.     p_in_v = p_pic->p[2].p_pixels;
  266.     p_in_end = p_in + p_pic->p[1].i_visible_lines * p_pic->p[1].i_pitch - 8;
  267.     p_out = p_outpic->p[1].p_pixels;
  268.     p_out_v = p_outpic->p[2].p_pixels;
  269.     i_sin = sin(f_hue) * 256;
  270.     i_cos = cos(f_hue) * 256;
  271.     i_x = ( cos(f_hue) + sin(f_hue) ) * 32768;
  272.     i_y = ( cos(f_hue) - sin(f_hue) ) * 32768;
  273.     if ( i_sat > 256 )
  274.     {
  275. #define WRITE_UV_CLIP() 
  276.     i_u = *p_in++ ; i_v = *p_in_v++ ; 
  277.     *p_out++ = clip( (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) 
  278.                            * i_sat) >> 8) + 128); 
  279.     *p_out_v++ = clip( (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) 
  280.                            * i_sat) >> 8) + 128)
  281.         uint8_t i_u, i_v;
  282.         for( ; p_in < p_in_end ; )
  283.         {
  284.             p_line_end = p_in + p_pic->p[1].i_visible_pitch - 8;
  285.             for( ; p_in < p_line_end ; )
  286.             {
  287.                 /* Do 8 pixels at a time */
  288.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  289.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  290.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  291.                 WRITE_UV_CLIP(); WRITE_UV_CLIP();
  292.             }
  293.             p_line_end += 8;
  294.             for( ; p_in < p_line_end ; )
  295.             {
  296.                 WRITE_UV_CLIP();
  297.             }
  298.             p_in += p_pic->p[1].i_pitch - p_pic->p[1].i_visible_pitch;
  299.             p_in_v += p_pic->p[2].i_pitch - p_pic->p[2].i_visible_pitch;
  300.             p_out += p_outpic->p[1].i_pitch - p_outpic->p[1].i_visible_pitch;
  301.             p_out_v += p_outpic->p[2].i_pitch - p_outpic->p[2].i_visible_pitch;
  302.         }
  303.     }
  304.     else
  305.     {
  306. #define WRITE_UV() 
  307.     i_u = *p_in++ ; i_v = *p_in_v++ ; 
  308.     *p_out++ = (( ((i_u * i_cos + i_v * i_sin - i_x) >> 8) 
  309.                        * i_sat) >> 8) + 128; 
  310.     *p_out_v++ = (( ((i_v * i_cos - i_u * i_sin - i_y) >> 8) 
  311.                        * i_sat) >> 8) + 128
  312.         uint8_t i_u, i_v;
  313.         for( ; p_in < p_in_end ; )
  314.         {
  315.             p_line_end = p_in + p_pic->p[1].i_visible_pitch - 8;
  316.             for( ; p_in < p_line_end ; )
  317.             {
  318.                 /* Do 8 pixels at a time */
  319.                 WRITE_UV(); WRITE_UV(); WRITE_UV(); WRITE_UV();
  320.                 WRITE_UV(); WRITE_UV(); WRITE_UV(); WRITE_UV();
  321.             }
  322.             p_line_end += 8;
  323.             for( ; p_in < p_line_end ; )
  324.             {
  325.                 WRITE_UV();
  326.             }
  327.             p_in += p_pic->p[1].i_pitch - p_pic->p[1].i_visible_pitch;
  328.             p_in_v += p_pic->p[2].i_pitch - p_pic->p[2].i_visible_pitch;
  329.             p_out += p_outpic->p[1].i_pitch - p_outpic->p[1].i_visible_pitch;
  330.             p_out_v += p_outpic->p[2].i_pitch - p_outpic->p[2].i_visible_pitch;
  331.         }
  332.     }
  333.     vout_UnlinkPicture( p_vout->p_sys->p_vout, p_outpic );
  334.     vout_DisplayPicture( p_vout->p_sys->p_vout, p_outpic );
  335. }
  336. /*****************************************************************************
  337.  * SendEvents: forward mouse and keyboard events to the parent p_vout
  338.  *****************************************************************************/
  339. static int SendEvents( vlc_object_t *p_this, char const *psz_var,
  340.                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
  341. {
  342.     var_Set( (vlc_object_t *)p_data, psz_var, newval );
  343.     return VLC_SUCCESS;
  344. }
  345. /*****************************************************************************
  346.  * SendEventsToChild: forward events to the child/children vout
  347.  *****************************************************************************/
  348. static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var,
  349.                        vlc_value_t oldval, vlc_value_t newval, void *p_data )
  350. {
  351.     vout_thread_t *p_vout = (vout_thread_t *)p_this;
  352.     var_Set( p_vout->p_sys->p_vout, psz_var, newval );
  353.     return VLC_SUCCESS;
  354. }