On Thu, 26 Jul 2012 22:51:17 +0000, Loren Merritt <[email protected]> 
wrote:
> ---
>  libavfilter/vf_hqdn3d.c |   70 
> +++++++++++++++++++++++++++++++----------------
>  1 files changed, 46 insertions(+), 24 deletions(-)
> 
> diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c
> index 02f0cd1..521fef8 100644
> --- a/libavfilter/vf_hqdn3d.c
> +++ b/libavfilter/vf_hqdn3d.c
> @@ -34,21 +34,24 @@
>  #include "video.h"
>  
>  typedef struct {
> -    int16_t coefs[4][512*16];
> +    int16_t *coefs[4];
>      uint16_t *line;
>      uint16_t *frame_prev[3];
> +    double strength[4];
>      int hsub, vsub;
>      int depth;
>  } HQDN3DContext;
>  
> +#define LUT_BITS (depth==16 ? 8 : 4)
>  #define RIGHTSHIFT(a,b) (((a)+(((1<<(b))-1)>>1))>>(b))
>  #define LOAD(x) ((depth==8 ? src[x] : AV_RN16A(src+(x)*2)) << (16-depth))
>  #define STORE(x,val) (depth==8 ? dst[x] = RIGHTSHIFT(val, 16-depth)\
>                      : AV_WN16A(dst+(x)*2, RIGHTSHIFT(val, 16-depth)))
>  
> -static inline uint32_t lowpass(int prev, int cur, int16_t *coef)
> +av_always_inline
> +static inline uint32_t lowpass(int prev, int cur, int16_t *coef, int depth)
>  {
> -    int d = (prev-cur)>>4;
> +    int d = (prev - cur) >> (8 - LUT_BITS);
>      return cur + coef[d];
>  }
>  
> @@ -61,11 +64,11 @@ static void denoise_temporal(uint8_t *src, uint8_t *dst,
>      long x, y;
>      uint32_t tmp;
>  
> -    temporal += 0x1000;
> +    temporal += 256 << LUT_BITS;
>  
>      for (y = 0; y < h; y++) {
>          for (x = 0; x < w; x++) {
> -            frame_ant[x] = tmp = lowpass(frame_ant[x], LOAD(x), temporal);
> +            frame_ant[x] = tmp = lowpass(frame_ant[x], LOAD(x), temporal, 
> depth);
>              STORE(x, tmp);
>          }
>          src += sstride;
> @@ -84,15 +87,15 @@ static void denoise_spatial(uint8_t *src, uint8_t *dst,
>      uint32_t pixel_ant;
>      uint32_t tmp;
>  
> -    spatial  += 0x1000;
> -    temporal += 0x1000;
> +    spatial  += 256 << LUT_BITS;
> +    temporal += 256 << LUT_BITS;
>  
>      /* First line has no top neighbor. Only left one for each tmp and
>       * last frame */
>      pixel_ant = LOAD(0);
>      for (x = 0; x < w; x++) {
> -        line_ant[x] = tmp = pixel_ant = lowpass(pixel_ant, LOAD(x), spatial);
> -        frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal);
> +        line_ant[x] = tmp = pixel_ant = lowpass(pixel_ant, LOAD(x), spatial, 
> depth);
> +        frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal, depth);
>          STORE(x, tmp);
>      }
>  
> @@ -102,13 +105,13 @@ static void denoise_spatial(uint8_t *src, uint8_t *dst,
>          frame_ant += w;
>          pixel_ant = LOAD(0);
>          for (x = 0; x < w-1; x++) {
> -            line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial);
> -            pixel_ant = lowpass(pixel_ant, LOAD(x+1), spatial);
> -            frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal);
> +            line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial, 
> depth);
> +            pixel_ant = lowpass(pixel_ant, LOAD(x+1), spatial, depth);
> +            frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal, depth);
>              STORE(x, tmp);
>          }
> -        line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial);
> -        frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal);
> +        line_ant[x] = tmp = lowpass(line_ant[x], pixel_ant, spatial, depth);
> +        frame_ant[x] = tmp = lowpass(frame_ant[x], tmp, temporal, depth);
>          STORE(x, tmp);
>      }
>  }
> @@ -119,6 +122,8 @@ static void denoise_depth(uint8_t *src, uint8_t *dst,
>                            int w, int h, int sstride, int dstride,
>                            int16_t *spatial, int16_t *temporal, int depth)
>  {
> +    // FIXME: For 16bit depth, frame_ant could be a pointer to the previous
> +    // filtered frame rather than a separate buffer.
>      long x, y;
>      uint16_t *frame_ant = *frame_ant_ptr;
>      if (!frame_ant) {
> @@ -143,24 +148,26 @@ static void denoise_depth(uint8_t *src, uint8_t *dst,
>      switch (hqdn3d->depth) {\
>          case  8: denoise_depth(__VA_ARGS__,  8); break;\
>          case 10: denoise_depth(__VA_ARGS__, 10); break;\
> +        case 16: denoise_depth(__VA_ARGS__, 16); break;\
>      }
>  
> -static void precalc_coefs(int16_t *ct, double dist25)
> +static int16_t *precalc_coefs(double dist25, int depth)
>  {
>      int i;
>      double gamma, simil, C;
> +    int16_t *ct = av_malloc((512<<LUT_BITS)*sizeof(int16_t));
>  
>      gamma = log(0.25) / log(1.0 - FFMIN(dist25,252.0)/255.0 - 0.00001);
>  
> -    for (i = -255*16; i <= 255*16; i++) {
> -        // lowpass() truncates (not rounds) the diff, so +15/32 for the 
> midpoint of the bin.
> -        double f = (i + 15.0/32.0) / 16.0;
> +    for (i = -255<<LUT_BITS; i <= 255<<LUT_BITS; i++) {
> +        double f = ((i<<(9-LUT_BITS)) + (1<<(8-LUT_BITS)) - 1) / 512.0; // 
> midpoint of the bin
>          simil = 1.0 - FFABS(f) / 255.0;
>          C = pow(simil, gamma) * 256.0 * f;
> -        ct[16*256+i] = lrint(C);
> +        ct[(256<<LUT_BITS)+i] = lrint(C);
>      }
>  
>      ct[0] = !!dist25;
> +    return ct;
>  }
>  
>  #define PARAM1_DEFAULT 4.0
> @@ -208,6 +215,11 @@ static int init(AVFilterContext *ctx, const char *args)
>          }
>      }
>  
> +    hqdn3d->strength[0] = lum_spac;
> +    hqdn3d->strength[1] = lum_tmp;
> +    hqdn3d->strength[2] = chrom_spac;
> +    hqdn3d->strength[3] = chrom_tmp;
> +
>      av_log(ctx, AV_LOG_VERBOSE, "ls:%lf cs:%lf lt:%lf ct:%lf\n",
>             lum_spac, chrom_spac, lum_tmp, chrom_tmp);
>      if (lum_spac < 0 || chrom_spac < 0 || isnan(chrom_tmp)) {
> @@ -217,11 +229,6 @@ static int init(AVFilterContext *ctx, const char *args)
>          return AVERROR(EINVAL);
>      }
>  
> -    precalc_coefs(hqdn3d->coefs[0], lum_spac);
> -    precalc_coefs(hqdn3d->coefs[1], lum_tmp);
> -    precalc_coefs(hqdn3d->coefs[2], chrom_spac);
> -    precalc_coefs(hqdn3d->coefs[3], chrom_tmp);
> -
>      return 0;
>  }
>  
> @@ -229,6 +236,10 @@ static void uninit(AVFilterContext *ctx)
>  {
>      HQDN3DContext *hqdn3d = ctx->priv;
>  
> +    av_freep(&hqdn3d->coefs[0]);
> +    av_freep(&hqdn3d->coefs[1]);
> +    av_freep(&hqdn3d->coefs[2]);
> +    av_freep(&hqdn3d->coefs[3]);
>      av_freep(&hqdn3d->line);
>      av_freep(&hqdn3d->frame_prev[0]);
>      av_freep(&hqdn3d->frame_prev[1]);
> @@ -251,6 +262,9 @@ static int query_formats(AVFilterContext *ctx)
>          AV_NE( PIX_FMT_YUV420P10BE, PIX_FMT_YUV420P10LE ),
>          AV_NE( PIX_FMT_YUV422P10BE, PIX_FMT_YUV422P10LE ),
>          AV_NE( PIX_FMT_YUV444P10BE, PIX_FMT_YUV444P10LE ),
> +        AV_NE( PIX_FMT_YUV420P16BE, PIX_FMT_YUV420P16LE ),
> +        AV_NE( PIX_FMT_YUV422P16BE, PIX_FMT_YUV422P16LE ),
> +        AV_NE( PIX_FMT_YUV444P16BE, PIX_FMT_YUV444P16LE ),
>          PIX_FMT_NONE
>      };
>  
> @@ -271,6 +285,14 @@ static int config_input(AVFilterLink *inlink)
>      if (!hqdn3d->line)
>          return AVERROR(ENOMEM);
>  
> +    for (int i=0; i<4; i++) {
> +        hqdn3d->coefs[i] = precalc_coefs(hqdn3d->strength[i], hqdn3d->depth);
> +        if (!hqdn3d->coefs[i]) {

precalc_coefs() doesn't check its malloc, so you would crash before
getting here

> +            uninit(inlink->dst);

You don't need to call uninit(), the filter is already inited so it's
the caller's responsibility to uninit it.

-- 
Anton Khirnov
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to