eq.c

来自「linux下的MPEG1」· C语言 代码 · 共 423 行

C
423
字号
/* * Copyright (C) 2000-2004 the xine project *  * This file is part of xine, a free video player. *  * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA * * $Id: eq.c,v 1.15 2007/03/22 23:32:05 dgp85 Exp $ * * mplayer's eq (soft video equalizer) * Copyright (C) Richard Felker */#include "xine_internal.h"#include "post.h"#include "xineutils.h"#include <pthread.h>#if defined(ARCH_X86) || defined(ARCH_X86_64)static void process_MMX(unsigned char *dest, int dstride, unsigned char *src, int sstride,		    int w, int h, int brightness, int contrast){	int i;	int pel;	int dstep = dstride-w;	int sstep = sstride-w;	short brvec[4];	short contvec[4];	contrast = ((contrast+100)*256*16)/100;	brightness = ((brightness+100)*511)/200-128 - contrast/32;	brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness;	contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast;			while (h--) {		asm volatile (			"movq (%5), %%mm3 \n\t"			"movq (%6), %%mm4 \n\t"			"pxor %%mm0, %%mm0 \n\t"			"movl %4, %%eax\n\t"			ASMALIGN(4)			"1: \n\t"			"movq (%0), %%mm1 \n\t"			"movq (%0), %%mm2 \n\t"			"punpcklbw %%mm0, %%mm1 \n\t"			"punpckhbw %%mm0, %%mm2 \n\t"			"psllw $4, %%mm1 \n\t"			"psllw $4, %%mm2 \n\t"			"pmulhw %%mm4, %%mm1 \n\t"			"pmulhw %%mm4, %%mm2 \n\t"			"paddw %%mm3, %%mm1 \n\t"			"paddw %%mm3, %%mm2 \n\t"			"packuswb %%mm2, %%mm1 \n\t"			"add $8, %0 \n\t"			"movq %%mm1, (%1) \n\t"			"add $8, %1 \n\t"			"decl %%eax \n\t"			"jnz 1b \n\t"			: "=r" (src), "=r" (dest)			: "0" (src), "1" (dest), "r" (w>>3), "r" (brvec), "r" (contvec)			: "%eax"		);		for (i = w&7; i; i--)		{			pel = ((*src++* contrast)>>12) + brightness;			if(pel&768) pel = (-pel)>>31;			*dest++ = pel;		}		src += sstep;		dest += dstep;	}	asm volatile ( "emms \n\t" ::: "memory" );}#endifstatic void process_C(unsigned char *dest, int dstride, unsigned char *src, int sstride,		    int w, int h, int brightness, int contrast){	int i;	int pel;	int dstep = dstride-w;	int sstep = sstride-w;	contrast = ((contrast+100)*256*256)/100;	brightness = ((brightness+100)*511)/200-128 - contrast/512;	while (h--) {		for (i = w; i; i--)		{			pel = ((*src++* contrast)>>16) + brightness;			if(pel&768) pel = (-pel)>>31;			*dest++ = pel;		}		src += sstep;		dest += dstep;	}}static void (*process)(unsigned char *dest, int dstride, unsigned char *src, int sstride,		       int w, int h, int brightness, int contrast);/* plugin class initialization function */void *eq_init_plugin(xine_t *xine, void *);typedef struct post_plugin_eq_s post_plugin_eq_t;/* * this is the struct used by "parameters api"  */typedef struct eq_parameters_s {  int brightness;  int contrast;} eq_parameters_t;/* * description of params struct */START_PARAM_DESCR( eq_parameters_t )PARAM_ITEM( POST_PARAM_TYPE_INT, brightness, NULL, -100, 100, 0,             "brightness" )PARAM_ITEM( POST_PARAM_TYPE_INT, contrast, NULL, -100, 100, 0,             "contrast" )END_PARAM_DESCR( param_descr )/* plugin structure */struct post_plugin_eq_s {  post_plugin_t post;  /* private data */  eq_parameters_t    params;  xine_post_in_t     params_input;  pthread_mutex_t    lock;};static int set_parameters (xine_post_t *this_gen, void *param_gen) {  post_plugin_eq_t *this = (post_plugin_eq_t *)this_gen;  eq_parameters_t *param = (eq_parameters_t *)param_gen;  pthread_mutex_lock (&this->lock);  memcpy( &this->params, param, sizeof(eq_parameters_t) );  pthread_mutex_unlock (&this->lock);  return 1;}static int get_parameters (xine_post_t *this_gen, void *param_gen) {  post_plugin_eq_t *this = (post_plugin_eq_t *)this_gen;  eq_parameters_t *param = (eq_parameters_t *)param_gen;  memcpy( param, &this->params, sizeof(eq_parameters_t) );  return 1;} static xine_post_api_descr_t * get_param_descr (void) {  return &param_descr;}static char * get_help (void) {  return _("Software equalizer with interactive controls just like the hardware "           "equalizer, for cards/drivers that do not support brightness and "           "contrast controls in hardware.\n"           "\n"           "Parameters\n"           "  brightness\n"           "  contrast\n"           "\n"           "Note: It is possible to use frontend's control window to set "           "these parameters.\n"           "\n"           "* mplayer's eq (C) Richard Felker\n"           );}static xine_post_api_t post_api = {  set_parameters,  get_parameters,  get_param_descr,  get_help,};/* plugin class functions */static post_plugin_t *eq_open_plugin(post_class_t *class_gen, int inputs,					 xine_audio_port_t **audio_target,					 xine_video_port_t **video_target);static char          *eq_get_identifier(post_class_t *class_gen);static char          *eq_get_description(post_class_t *class_gen);static void           eq_class_dispose(post_class_t *class_gen);/* plugin instance functions */static void           eq_dispose(post_plugin_t *this_gen);/* replaced video_port functions */static int            eq_get_property(xine_video_port_t *port_gen, int property);static int            eq_set_property(xine_video_port_t *port_gen, int property, int value);/* frame intercept check */static int            eq_intercept_frame(post_video_port_t *port, vo_frame_t *frame);/* replaced vo_frame functions */static int            eq_draw(vo_frame_t *frame, xine_stream_t *stream);void *eq_init_plugin(xine_t *xine, void *data){  post_class_t *class = (post_class_t *)malloc(sizeof(post_class_t));  if (!class)    return NULL;    class->open_plugin     = eq_open_plugin;  class->get_identifier  = eq_get_identifier;  class->get_description = eq_get_description;  class->dispose         = eq_class_dispose;  return class;}static post_plugin_t *eq_open_plugin(post_class_t *class_gen, int inputs,					 xine_audio_port_t **audio_target,					 xine_video_port_t **video_target){  post_plugin_eq_t  *this = (post_plugin_eq_t *)xine_xmalloc(sizeof(post_plugin_eq_t));  post_in_t         *input;  xine_post_in_t    *input_api;  post_out_t        *output;  post_video_port_t *port;    if (!this || !video_target || !video_target[0]) {    free(this);    return NULL;  }  process = process_C;#if defined(ARCH_X86) || defined(ARCH_X86_64)  if( xine_mm_accel() & MM_ACCEL_X86_MMX )     process = process_MMX;#endif  _x_post_init(&this->post, 0, 1);  this->params.brightness = 0;  this->params.contrast = 0;  pthread_mutex_init (&this->lock, NULL);    port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);  port->new_port.get_property = eq_get_property;  port->new_port.set_property = eq_set_property;  port->intercept_frame       = eq_intercept_frame;  port->new_frame->draw       = eq_draw;  input_api       = &this->params_input;    input_api->name = "parameters";  input_api->type = XINE_POST_DATA_PARAMETERS;  input_api->data = &post_api;  xine_list_push_back(this->post.input, input_api);  input->xine_in.name     = "video";  output->xine_out.name   = "eqd video";    this->post.xine_post.video_input[0] = &port->new_port;    this->post.dispose = eq_dispose;    return &this->post;}static char *eq_get_identifier(post_class_t *class_gen){  return "eq";}static char *eq_get_description(post_class_t *class_gen){  return "soft video equalizer";}static void eq_class_dispose(post_class_t *class_gen){  free(class_gen);}static void eq_dispose(post_plugin_t *this_gen){  post_plugin_eq_t *this = (post_plugin_eq_t *)this_gen;  if (_x_post_dispose(this_gen)) {    pthread_mutex_destroy(&this->lock);    free(this);  }}static int eq_get_property(xine_video_port_t *port_gen, int property) {  post_video_port_t *port = (post_video_port_t *)port_gen;  post_plugin_eq_t *this = (post_plugin_eq_t *)port->post;  if( property == XINE_PARAM_VO_BRIGHTNESS )    return 65535 * (this->params.brightness + 100) / 200;  else if( property == XINE_PARAM_VO_CONTRAST )    return 65535 * (this->params.contrast + 100) / 200;  else    return port->original_port->get_property(port->original_port, property);}static int eq_set_property(xine_video_port_t *port_gen, int property, int value) {  post_video_port_t *port = (post_video_port_t *)port_gen;  post_plugin_eq_t *this = (post_plugin_eq_t *)port->post;  if( property == XINE_PARAM_VO_BRIGHTNESS ) {    pthread_mutex_lock (&this->lock);    this->params.brightness = (200 * value / 65535) - 100;    pthread_mutex_unlock (&this->lock);    return value;  } else if( property == XINE_PARAM_VO_CONTRAST ) {    pthread_mutex_lock (&this->lock);    this->params.contrast = (200 * value / 65535) - 100;    pthread_mutex_unlock (&this->lock);    return value;  } else    return port->original_port->set_property(port->original_port, property, value);}static int eq_intercept_frame(post_video_port_t *port, vo_frame_t *frame){  return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2);}static int eq_draw(vo_frame_t *frame, xine_stream_t *stream){  post_video_port_t *port = (post_video_port_t *)frame->port;  post_plugin_eq_t *this = (post_plugin_eq_t *)port->post;  vo_frame_t *out_frame;  vo_frame_t *yv12_frame;  int skip;  if( !frame->bad_frame &&      ((this->params.brightness != 0) || (this->params.contrast != 0)) ) {    /* convert to YV12 if needed */    if( frame->format != XINE_IMGFMT_YV12 ) {      yv12_frame = port->original_port->get_frame(port->original_port,        frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);        _x_post_frame_copy_down(frame, yv12_frame);        yuy2_to_yv12(frame->base[0], frame->pitches[0],                   yv12_frame->base[0], yv12_frame->pitches[0],                   yv12_frame->base[1], yv12_frame->pitches[1],                   yv12_frame->base[2], yv12_frame->pitches[2],                   frame->width, frame->height);      } else {      yv12_frame = frame;      yv12_frame->lock(yv12_frame);    }    out_frame = port->original_port->get_frame(port->original_port,      frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);    _x_post_frame_copy_down(frame, out_frame);    pthread_mutex_lock (&this->lock);    process(out_frame->base[0], out_frame->pitches[0],            yv12_frame->base[0], yv12_frame->pitches[0],            frame->width, frame->height,            this->params.brightness, this->params.contrast);    xine_fast_memcpy(out_frame->base[1],yv12_frame->base[1],                     yv12_frame->pitches[1] * frame->height/2);    xine_fast_memcpy(out_frame->base[2],yv12_frame->base[2],                     yv12_frame->pitches[2] * frame->height/2);    pthread_mutex_unlock (&this->lock);    skip = out_frame->draw(out_frame, stream);      _x_post_frame_copy_up(frame, out_frame);    out_frame->free(out_frame);    yv12_frame->free(yv12_frame);  } else {    _x_post_frame_copy_down(frame, frame->next);    skip = frame->next->draw(frame->next, stream);    _x_post_frame_copy_up(frame, frame->next);  }  return skip;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?