[MPlayer-dev-eng] [PATCH] vf_eq2 + vf_eq

D Richard Felker III dalias at aerifal.cx
Fri Jan 31 22:54:32 CET 2003


On Fri, Jan 31, 2003 at 10:21:32PM +0100, Hampa Hug wrote:
> Hello
> 
> Based on the discussion in the other thread I made a new
> patch to vf_eq2.c that essentially combines vf_eq.c and
> vf_eq2.c. It is not well testet yet.

The idea is good, but I don't think you should be passing around
vf_eq2_t like that. Instead just pass the individual params that are
needed. Why? Well, for one thing, adjust_y_*() can also do saturation,
with no changes, except that you have to pass it the saturation values
and u plane info. Also adjust_u and adjust_v are identical except for
which params they use, so it's wasteful (and cache-inefficient) to
call one then the other instead of calling the same function twice
with different params.

Also, you should name the functions by what they do. E.g.
adjust_y_MMX -> affine_1d_MMX or something, rather than just
"adjust_{plane}".

Rich


> 
> Hampa

> diff -Nur mplayer-cvs/libmpcodecs/vf_eq2.c mplayer-hampa/libmpcodecs/vf_eq2.c
> --- mplayer-cvs/libmpcodecs/vf_eq2.c	2002-12-06 19:47:27.000000000 +0100
> +++ mplayer-hampa/libmpcodecs/vf_eq2.c	2003-01-31 22:11:39.000000000 +0100
> @@ -1,9 +1,10 @@
>  /*
>   * vf_eq2.c
>   *
> - * LUT-based software equalizer (brightness, contrast, gamma)
> + * Software equalizer (brightness, contrast, gamma, hue, saturation)
>   *
> - * Hampa Hug <hhug at student.ethz.ch>
> + * Hampa Hug <hampa at hampa.ch>
> + * Daniel Moreno <comac at comac.darktech.org>
>   *
>   */
>  
> @@ -12,8 +13,8 @@
>  #include <string.h>
>  #include <math.h>
>  
> -#include "../config.h"
> -#include "../mp_msg.h"
> +#include "config.h"
> +#include "mp_msg.h"
>  
>  #include "img_format.h"
>  #include "mp_image.h"
> @@ -25,104 +26,446 @@
>  
>  
>  typedef struct vf_priv_s {
> -  unsigned char *buf;
> -  int           buf_w;
> -  int           buf_h;
> +  void (*adjust_y) (struct vf_priv_s *eq2, mp_image_t *dst, mp_image_t *src);
> +  void (*adjust_u) (struct vf_priv_s *eq2, mp_image_t *dst, mp_image_t *src);
> +  void (*adjust_v) (struct vf_priv_s *eq2, mp_image_t *dst, mp_image_t *src);
> +  void (*adjust_uv) (struct vf_priv_s *eq2, mp_image_t *dst, mp_image_t *src);
>  
>    double        contrast;
> -  double        bright;
> +  double        brightness;
>    double        gamma;
> +  double        hue;
> +  double        saturation;
>  
> -  unsigned char lut[256];
> +  double        rgamma;
> +  double        ggamma;
> +  double        bgamma;
> +
> +  int           cos_h;
> +  int           sin_h;
> +
> +  unsigned char lut_y[256];
> +  unsigned char lut_u[256];
> +  unsigned char lut_v[256];
> +
> +  unsigned long buf_n;
> +  unsigned char *buf_y;
> +  unsigned char *buf_u;
> +  unsigned char *buf_v;
>  } vf_eq2_t;
>  
>  
> +
> +#ifdef HAVE_MMX
> +static
> +void adjust_y_MMX (vf_eq2_t *eq2, mp_image_t *dst, mp_image_t *src)
> +{
> +  int           i;
> +  int           w, h;
> +  int           contrast, brightness;
> +  unsigned char *src_y, *dst_y;
> +  int           dstep, sstep;
> +  int           pel;
> +  short         brvec[4];
> +  short         contvec[4];
> +
> +  contrast = (int) (eq2->contrast * 256 * 16);
> +  brightness = ((int) (100.0 * eq2->brightness + 100.0) * 511) / 200 - 128 - contrast / 32;
> +
> +  brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness;
> +  contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast;
> +
> +  w = src->w;
> +  h = src->h;
> +
> +  sstep = src->stride[0] - w;
> +  dstep = dst->stride[0] - w;
> +
> +  src_y = src->planes[0];
> +  dst_y = dst->planes[0];
> +
> +  while (h-- > 0) {
> +    asm volatile (
> +      "movq (%5), %%mm3 \n\t"
> +      "movq (%6), %%mm4 \n\t"
> +      "pxor %%mm0, %%mm0 \n\t"
> +      "movl %4, %%eax\n\t"
> +      ".balign 16 \n\t"
> +      "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"
> +      "addl $8, %0 \n\t"
> +      "movq %%mm1, (%1) \n\t"
> +      "addl $8, %1 \n\t"
> +      "decl %%eax \n\t"
> +      "jnz 1b \n\t"
> +      : "=r" (src_y), "=r" (dst_y)
> +      : "0" (src_y), "1" (dst_y), "r" (w>>3), "r" (brvec), "r" (contvec)
> +      : "%eax"
> +    );
> +
> +    for (i = w & 7; i > 0; i--) {
> +      pel = ((*src_y++* contrast) >> 12) + brightness;
> +      if (pel & 768) {
> +        pel = (-pel) >> 31;
> +      }
> +      *dst_y++ = pel;
> +    }
> +
> +    src_y += sstep;
> +    dst_y += dstep;
> +  }
> +
> +  asm volatile ( "emms \n\t" ::: "memory" );
> +}
> +#endif
> +
> +static
> +void adjust_y (vf_eq2_t *eq2, mp_image_t *dst, mp_image_t *src)
> +{
> +  int           i, j;
> +  unsigned char *src_y, *dst_y;
> +  unsigned char *lut;
> +
> +  lut = eq2->lut_y;
> +
> +  src_y = src->planes[0];
> +  dst_y = dst->planes[0];
> +
> +  for (j = 0; j < dst->h; j++) {
> +    for (i = 0; i < dst->w; i++) {
> +      dst_y[i] = lut[src_y[i]];
> +    }
> +
> +    src_y += src->stride[0];
> +    dst_y += dst->stride[0];
> +  }
> +}
> +
> +static
> +void adjust_u (vf_eq2_t *eq2, mp_image_t *dst, mp_image_t *src)
> +{
> +  int           i, j, w, h;
> +  unsigned char *src_u, *dst_u;
> +  unsigned char *lut_u;
> +
> +  lut_u = eq2->lut_u;
> +
> +  src_u = src->planes[1];
> +  dst_u = dst->planes[1];
> +
> +  w = src->w >> src->chroma_x_shift;
> +  h = src->h >> src->chroma_y_shift;
> +
> +  for (j = 0; j < h; j++) {
> +    for (i = 0; i < w; i++) {
> +      dst_u[i] = lut_u[src_u[i]];
> +    }
> +
> +    src_u += src->stride[1];
> +    dst_u += dst->stride[1];
> +  }
> +}
> +
>  static
> -void create_lut (vf_eq2_t *eq2)
> +void adjust_v (vf_eq2_t *eq2, mp_image_t *dst, mp_image_t *src)
> +{
> +  int           i, j, w, h;
> +  unsigned char *src_v, *dst_v;
> +  unsigned char *lut_v;
> +
> +  lut_v = eq2->lut_v;
> +
> +  src_v = src->planes[2];
> +  dst_v = dst->planes[2];
> +
> +  w = src->w >> src->chroma_x_shift;
> +  h = src->h >> src->chroma_y_shift;
> +
> +  for (j = 0; j < h; j++) {
> +    for (i = 0; i < w; i++) {
> +      dst_v[i] = lut_v[src_v[i]];
> +    }
> +
> +    src_v += src->stride[2];
> +    dst_v += dst->stride[2];
> +  }
> +}
> +
> +static
> +void adjust_hue (vf_eq2_t *eq2, mp_image_t *dst, mp_image_t *src)
> +{
> +  int           x, y, w, h;
> +  long          u, v, t;
> +  unsigned char *src_u, *dst_u;
> +  unsigned char *src_v, *dst_v;
> +
> +  w = dst->w >> dst->chroma_x_shift;
> +  h = dst->h >> dst->chroma_y_shift;
> +
> +  src_u = src->planes[1];
> +  src_v = src->planes[2];
> +  dst_u = dst->planes[1];
> +  dst_v = dst->planes[2];
> +
> +  for (y = 0; y < h; y++) {
> +    for (x = 0; x < w; x++) {
> +      u = (long) src_u[x] - 128;
> +      v = (long) src_v[x] - 128;
> +
> +      t = (eq2->cos_h * u - eq2->sin_h * v) / 1024;
> +      v = (eq2->sin_h * u + eq2->cos_h * v) / 1024;
> +      u = t;
> +
> +      u += 128;
> +      v += 128;
> +
> +      u = (u < 0) ? 0 : ((u > 255) ? 255 : u);
> +      v = (v < 0) ? 0 : ((v > 255) ? 255 : v);
> +
> +      dst_u[x] = (unsigned char) u;
> +      dst_v[x] = (unsigned char) v;
> +    }
> +
> +    src_u += src->stride[1];
> +    src_v += src->stride[2];
> +    dst_u += dst->stride[1];
> +    dst_v += dst->stride[2];
> +  }
> +}
> +
> +static
> +int put_image (vf_instance_t *vf, mp_image_t *src)
> +{
> +  vf_eq2_t      *eq2;
> +  mp_image_t    *dst;
> +  unsigned long img_n;
> +
> +  eq2 = vf->priv;
> +
> +  img_n = src->w * src->h;
> +
> +  if (eq2->buf_n != (3 * img_n) / 2) {
> +    eq2->buf_n = (3 * img_n) / 2;
> +    eq2->buf_y = (unsigned char *) realloc (eq2->buf_y, eq2->buf_n);
> +    eq2->buf_u = eq2->buf_y + img_n;
> +    eq2->buf_v = eq2->buf_y + img_n + img_n / 4;
> +  }
> +
> +  dst = vf_get_image (vf->next, src->imgfmt, MP_IMGTYPE_EXPORT, 0, src->w, src->h);
> +
> +  if (eq2->adjust_y != NULL) {
> +    dst->planes[0] = eq2->buf_y;
> +    dst->stride[0] = src->w;
> +    eq2->adjust_y (eq2, dst, src);
> +  }
> +  else {
> +    dst->planes[0] = src->planes[0];
> +    dst->stride[0] = src->stride[0];
> +  }
> +
> +  if (eq2->adjust_uv != NULL) {
> +    dst->planes[1] = eq2->buf_u;
> +    dst->stride[1] = src->w / 2;
> +    dst->planes[2] = eq2->buf_v;
> +    dst->stride[1] = src->w / 2;
> +    eq2->adjust_uv (eq2, dst, src);
> +    src = dst;
> +  }
> +
> +  if (eq2->adjust_u != NULL) {
> +    dst->planes[1] = eq2->buf_u;
> +    dst->stride[1] = src->w / 2;
> +    eq2->adjust_u (eq2, dst, src);
> +  }
> +  else {
> +    dst->planes[1] = src->planes[1];
> +    dst->stride[1] = src->stride[1];
> +  }
> +
> +  if (eq2->adjust_v != NULL) {
> +    dst->planes[2] = eq2->buf_v;
> +    dst->stride[1] = src->w / 2;
> +    eq2->adjust_v (eq2, dst, src);
> +  }
> +  else {
> +    dst->planes[2] = src->planes[2];
> +    dst->stride[2] = src->stride[2];
> +  }
> +
> +  return vf_next_put_image (vf, dst);
> +}
> +
> +static
> +void check_values (vf_eq2_t *eq2)
> +{
> +  /* yuck! floating point comparisons... */
> +
> +  if ((eq2->contrast == 1.0) && (eq2->brightness == 0.0) && (eq2->gamma == 1.0) && (eq2->ggamma == 1.0)) {
> +    eq2->adjust_y = NULL;
> +  }
> +#ifdef HAVE_MMX
> +  else if ((eq2->gamma == 1.0) && (eq2->ggamma == 1.0)) {
> +    eq2->adjust_y = &adjust_y_MMX;
> +  }
> +#endif
> +  else {
> +    eq2->adjust_y = &adjust_y;
> +  }
> +
> +  if ((eq2->saturation == 1.0) && (eq2->bgamma == 1.0)) {
> +    eq2->adjust_u = NULL;
> +  }
> +  else {
> +    eq2->adjust_u = &adjust_u;
> +  }
> +
> +  if ((eq2->saturation == 1.0) && (eq2->rgamma == 1.0)) {
> +    eq2->adjust_v = NULL;
> +  }
> +  else {
> +    eq2->adjust_v = &adjust_v;
> +  }
> +
> +  if (eq2->hue == 0.0) {
> +    eq2->adjust_uv = NULL;
> +  }
> +  else {
> +    eq2->adjust_uv = &adjust_hue;
> +  }
> +
> +  mp_msg (MSGT_VFILTER, MSGL_INFO, "vf_eq2: c=%.2f b=%.2f g=%.4f h=%.2f s=%.2f\n",
> +    eq2->contrast, eq2->brightness, eq2->gamma,
> +    180.0 * eq2->hue / 3.1415926, eq2->saturation
> +  );
> +}
> +
> +static
> +void create_lut_y (vf_eq2_t *eq2)
>  {
>    unsigned i;
> -  double   c, b, g;
> -  double   v;
> +  double   g, v;
>  
> -  c = eq2->contrast;
> -  b = eq2->bright;
> -  g = eq2->gamma;
> +  g = eq2->gamma * eq2->ggamma;
>  
>    if ((g < 0.001) || (g > 1000.0)) {
>      g = 1.0;
>    }
>  
> -  fprintf (stderr, "vf_eq2: c=%.2f b=%.2f g=%.4f\n", c, b, g);
> -
>    g = 1.0 / g;
>  
>    for (i = 0; i < 256; i++) {
>      v = (double) i / 255.0;
> -    v = c * (v - 0.5) + 0.5 + b;
> +    v = eq2->contrast * (v - 0.5) + 0.5 + eq2->brightness;
>  
>      if (v <= 0.0) {
> -      eq2->lut[i] = 0;
> +      eq2->lut_y[i] = 0;
>      }
>      else {
>        v = pow (v, g);
>  
>        if (v >= 1.0) {
> -        eq2->lut[i] = 255;
> +        eq2->lut_y[i] = 255;
>        }
>        else {
> -        /* we divided by 255.0 so now we also multiply by 255.0, not
> -           by 256.0. "+ 0.5" ensures proper rounding */
> -        eq2->lut[i] = (unsigned char) (255.0 * v + 0.5);
> +        eq2->lut_y[i] = (unsigned char) (256.0 * v);
>        }
>      }
>    }
>  }
>  
> -/* could inline this */
>  static
> -void process (unsigned char *dst, int dstride, unsigned char *src, int sstride,
> -  int w, int h, unsigned char lut[256])
> +void create_lut_uv (vf_eq2_t *eq2)
>  {
> -  int i, j;
> +  unsigned i;
> +  double   v;
> +  double   ugamma, vgamma;
>  
> -  for (j = 0; j < h; j++) {
> -    for (i = 0; i < w; i++) {
> -      dst[i] = lut[src[i]];
> +  ugamma = sqrt(eq2->ggamma / eq2->bgamma);
> +  vgamma = sqrt(eq2->ggamma / eq2->rgamma);
> +
> +  for (i = 0; i < 256; i++) {
> +    v = (double) i / 255.0 - 0.5;
> +    v *= eq2->saturation;
> +    v += 0.5;
> +
> +    if (v <= 0.0) {
> +      eq2->lut_u[i] = 0;
> +    }
> +    else if (v >= 1.0) {
> +      eq2->lut_u[i] = 255;
> +    }
> +    else {
> +      eq2->lut_u[i] = (unsigned char) (256.0 * pow(v, ugamma));
> +      eq2->lut_v[i] = (unsigned char) (256.0 * pow(v, vgamma));
>      }
> -    src += sstride;
> -    dst += dstride;
>    }
>  }
>  
>  static
> -int put_image (vf_instance_t *vf, mp_image_t *src)
> +void set_contrast (vf_eq2_t *eq2, double c)
>  {
> -  mp_image_t *dst;
> -  vf_eq2_t   *eq2;
> +  eq2->contrast = c;
>  
> -  eq2 = vf->priv;
> +  check_values (eq2);
> +  create_lut_y (eq2);
> +}
>  
> -  if ((eq2->buf == NULL) || (eq2->buf_w != src->stride[0]) || (eq2->buf_h != src->h)) {
> -    eq2->buf = (unsigned char *) realloc (eq2->buf, src->stride[0] * src->h);
> -    eq2->buf_w = src->stride[0];
> -    eq2->buf_h = src->h;
> -  }
> +static
> +void set_brightness (vf_eq2_t *eq2, double b)
> +{
> +  eq2->brightness = b;
>  
> -  dst = vf_get_image (vf->next, src->imgfmt, MP_IMGTYPE_EXPORT, 0, src->w, src->h);
> +  check_values (eq2);
> +  create_lut_y (eq2);
> +}
>  
> -  dst->stride[0] = src->stride[0];
> -  dst->stride[1] = src->stride[1];
> -  dst->stride[2] = src->stride[2];
> -  dst->planes[0] = vf->priv->buf;
> -  dst->planes[1] = src->planes[1];
> -  dst->planes[2] = src->planes[2];
> -
> -  process (
> -    dst->planes[0], dst->stride[0], src->planes[0], src->stride[0],
> -    src->w, src->h, eq2->lut
> -  );
> +static
> +void set_gamma (vf_eq2_t *eq2, double g)
> +{
> +  eq2->gamma = g;
>  
> -  return vf_next_put_image (vf, dst);
> +  check_values (eq2);
> +  create_lut_y (eq2);
> +}
> +
> +static
> +void set_hue (vf_eq2_t *eq2, double h)
> +{
> +  eq2->hue = h;
> +  eq2->cos_h = (int) (1024.0 * cos (h));
> +  eq2->sin_h = (int) (1024.0 * sin (h));
> +
> +  check_values (eq2);
> +}
> +
> +static
> +void set_saturation (vf_eq2_t *eq2, double s)
> +{
> +  eq2->saturation = s;
> +
> +  check_values (eq2);
> +  create_lut_uv (eq2);
> +}
> +
> +static
> +void init_params (vf_eq2_t *eq2)
> +{
> +  eq2->cos_h = (int) (1024.0 * cos (eq2->hue));
> +  eq2->sin_h = (int) (1024.0 * sin (eq2->hue));
> +
> +  check_values (eq2);
> +  create_lut_y (eq2);
> +  create_lut_uv (eq2);
>  }
>  
>  static
> @@ -135,18 +478,23 @@
>        eq = (vf_equalizer_t *) data;
>  
>        if (strcmp (eq->item, "gamma") == 0) {
> -        vf->priv->gamma = exp (log (8.0) * eq->value / 100.0);
> -        create_lut (vf->priv);
> +        set_gamma (vf->priv, exp (log (8.0) * eq->value / 100.0));
>          return CONTROL_TRUE;
>        }
>        else if (strcmp (eq->item, "contrast") == 0) {
> -        vf->priv->contrast = (1.0 / 100.0) * (eq->value + 100);
> -        create_lut (vf->priv);
> +        set_contrast (vf->priv, (1.0 / 100.0) * (eq->value + 100));
>          return CONTROL_TRUE;
>        }
>        else if (strcmp (eq->item, "brightness") == 0) {
> -        vf->priv->bright = (1.0 / 100.0) * eq->value;
> -        create_lut (vf->priv);
> +        set_brightness (vf->priv, (1.0 / 100.0) * eq->value);
> +        return CONTROL_TRUE;
> +      }
> +      else if (strcmp (eq->item, "hue") == 0) {
> +        set_hue (vf->priv, 3.1415926 * eq->value / 100.0);
> +        return CONTROL_TRUE;
> +      }
> +      else if (strcmp (eq->item, "saturation") == 0) {
> +        set_saturation (vf->priv, (double) (eq->value + 100) / 100.0);
>          return CONTROL_TRUE;
>        }
>        break;
> @@ -162,7 +510,15 @@
>          return CONTROL_TRUE;
>        }
>        else if (strcmp (eq->item, "brightness") == 0) {
> -        eq->value = (int) (100.0 * vf->priv->bright);
> +        eq->value = (int) (100.0 * vf->priv->brightness);
> +        return CONTROL_TRUE;
> +      }
> +      else if (strcmp (eq->item, "hue") == 0) {
> +        eq->value = (int) (100.0 * vf->priv->hue / 3.1415926);
> +        return CONTROL_TRUE;
> +      }
> +      else if (strcmp (eq->item, "saturation") == 0) {
> +        eq->value = (int) (100.0 * vf->priv->saturation) - 100;
>          return CONTROL_TRUE;
>        }
>        break;
> @@ -175,18 +531,9 @@
>  int query_format (vf_instance_t *vf, unsigned fmt)
>  {
>    switch (fmt) {
> -    case IMGFMT_YVU9:
> -    case IMGFMT_IF09:
>      case IMGFMT_YV12:
>      case IMGFMT_I420:
>      case IMGFMT_IYUV:
> -    case IMGFMT_CLPL:
> -    case IMGFMT_Y800:
> -    case IMGFMT_Y8:
> -    case IMGFMT_NV12:
> -    case IMGFMT_444P:
> -    case IMGFMT_422P:
> -    case IMGFMT_411P:
>        return vf_next_query_format (vf, fmt);
>    }
>  
> @@ -197,7 +544,7 @@
>  void uninit (vf_instance_t *vf)
>  {
>    if (vf->priv != NULL) {
> -    free (vf->priv->buf);
> +    free (vf->priv->buf_y);
>      free (vf->priv);
>    }
>  }
> @@ -215,31 +562,39 @@
>    vf->priv = (vf_eq2_t *) malloc (sizeof (vf_eq2_t));
>    eq2 = vf->priv;
>  
> -  eq2->buf = NULL;
> -  eq2->buf_w = 0;
> -  eq2->buf_h = 0;
> +  eq2->buf_y = NULL;
> +  eq2->buf_n = 0;
>  
> -  eq2->gamma = 1.0;
>    eq2->contrast = 1.0;
> -  eq2->bright = 0.0;
> +  eq2->brightness = 0.0;
> +  eq2->gamma = 1.0;
> +  eq2->hue = 0.0;
> +  eq2->saturation = 1.0;
> +  eq2->rgamma = 1.0;
> +  eq2->ggamma = 1.0;
> +  eq2->bgamma = 1.0;
>  
>    if (args != NULL) {
>  #ifdef USE_SETLOCALE
>      setlocale( LC_NUMERIC, "C" );
>  #endif
> -    sscanf (args, "%lf:%lf:%lf", &eq2->gamma, &eq2->contrast, &eq2->bright);
> +    sscanf (args, "%lf:%lf:%lf:%lf:%lf:%lf:%lf:%lf",
> +      &eq2->gamma, &eq2->contrast, &eq2->brightness,
> +      &eq2->hue, &eq2->saturation,
> +      &eq2->rgamma, &eq2->ggamma, &eq2->bgamma
> +    );
>  #ifdef USE_SETLOCALE
>      setlocale( LC_NUMERIC, "" );
>  #endif
>    }
>  
> -  create_lut (eq2);
> +  init_params (eq2);
>  
>    return 1;
>  }
>  
>  vf_info_t vf_info_eq2 = {
> -  "LUT-based software equalizer",
> +  "Software equalizer",
>    "eq2",
>    "Hampa Hug",
>    "",

> _______________________________________________
> MPlayer-dev-eng mailing list
> MPlayer-dev-eng at mplayerhq.hu
> http://mplayerhq.hu/mailman/listinfo/mplayer-dev-eng



More information about the MPlayer-dev-eng mailing list