~ubuntu-branches/ubuntu/natty/gst-entrans/natty

« back to all changes in this revision

Viewing changes to gst/mencoder/gsthqdn3d.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2010-09-13 19:49:29 UTC
  • Revision ID: james.westby@ubuntu.com-20100913194929-qz90a14xyxln9yfz
Tags: upstream-0.10.2
ImportĀ upstreamĀ versionĀ 0.10.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GStreamer Filter
 
2
 * Copyright (C) 2006 Mark Nauwelaerts <mnauw@users.sourceforge.net>
 
3
 *
 
4
 * mplayer hqdn3d filter
 
5
 *   Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
 
6
 *
 
7
 * mplayer/transcode denoise3d filter
 
8
 *   Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
 
9
 *   Copyright (C) 2003 Erik Slagter <erik@oldconomy.org> (GPL) 2003
 
10
 *      transcode optimizations
 
11
 *
 
12
 * This program is free software; you can redistribute it and/or modify
 
13
 * it under the terms of the GNU General Public License as published by
 
14
 * the Free Software Foundation; either version 2 of the License, or
 
15
 * (at your option) any later version.
 
16
 *
 
17
 * This program is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 * GNU General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU General Public License
 
23
 * along with this program; if not, write to the Free Software
 
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02110-1307  USA
 
25
 */
 
26
 
 
27
/**
 
28
 * SECTION:element-hqdn3d
 
29
 *
 
30
 * <refsect2>
 
31
 * <para>
 
32
 * This filter aims to reduce image noise  producing  smooth  images  and  making
 
33
 * still images really still (This should enhance compressibility).
 
34
 * </para>
 
35
 * <para>
 
36
 * Depending on <link linkend="GstHqdn3d--high-quality">hiqh-quality</link> setting,
 
37
 * it runs either mplayer's hqdn3d filter algorithm or the denoise3d algorithm,
 
38
 * which is cruder and simpler, but also faster.
 
39
 * </para>
 
40
 * <para>
 
41
 * Leaving or setting any of the other parameters to 0 will make the filter
 
42
 * use the indicated internal defaults.  Setting some parameters will
 
43
 * also have this value 'trickle' into the other parameters as follows:
 
44
 * <itemizedlist>
 
45
 * <listitem>
 
46
 * luma_spatial --> luma_temp, chroma_spatial, chroma_temp
 
47
 * </listitem>
 
48
 * <listitem>
 
49
 * chroma_spatial --> chroma_temp
 
50
 * </listitem>
 
51
 * <listitem>
 
52
 * luma_temp --> chroma_temp
 
53
 * </listitem>
 
54
 * </itemizedlist>
 
55
 * In addition, setting a components (both) parameters to a negative value will not
 
56
 * have the filter applied to this component.
 
57
 * </para>
 
58
 * <title>History</title>
 
59
 * <para>
 
60
 * <itemizedlist>
 
61
 * <listitem>
 
62
 * Mplayer denoise3d and hqdn3d filter [Daniel Moreno]
 
63
 * </listitem>
 
64
 * <listitem>
 
65
 * Also used in transcode; denoise3d filter somewhat optimized [Erik Slagter]
 
66
 * </listitem>
 
67
 * <listitem>
 
68
 * Also available in avidemux (MPlayer hqdn3d, MPlayer denoise3d)
 
69
 * </listitem>
 
70
 * </itemizedlist>
 
71
 * </para>
 
72
 * </refsect2>
 
73
 *
 
74
 */
 
75
 
 
76
 
 
77
#ifdef HAVE_CONFIG_H
 
78
#include "config.h"
 
79
#endif
 
80
 
 
81
#include "plugin-mencoder.h"
 
82
 
 
83
#include <math.h>
 
84
 
 
85
 
 
86
#define GST_TYPE_HQDN3D \
 
87
  (gst_hqdn3d_get_type())
 
88
#define GST_HQDN3D(obj) \
 
89
  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_HQDN3D,GstHqdn3d))
 
90
#define GST_HQDN3D_CLASS(klass) \
 
91
  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_HQDN3D,GstHqdn3dClass))
 
92
#define GST_IS_HQDN3D(obj) \
 
93
  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_HQDN3D))
 
94
#define GST_IS_HQDN3D_CLASS(klass) \
 
95
  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_HQDN3D))
 
96
 
 
97
typedef struct _GstHqdn3d GstHqdn3d;
 
98
typedef struct _GstHqdn3dClass GstHqdn3dClass;
 
99
 
 
100
/* number of coefficients for each 'dimension' */
 
101
#define COEFS_SIZE             512*16
 
102
 
 
103
/* function that will do the actual denoising */
 
104
typedef void (*GstDenoiseFunction) (guint8 * frame, guint * lineant,
 
105
                                    gushort ** frameprevptr,
 
106
                                    gint w, gint h,
 
107
                                    gint * horizontal, gint * vertical, gint * temporal);
 
108
 
 
109
 
 
110
struct _GstHqdn3d
 
111
{
 
112
  GstVideoFilter videofilter;
 
113
 
 
114
  gint width, height;
 
115
 
 
116
  /* user denoise parameters */
 
117
  gdouble set_luma_spatial, set_luma_temp, set_chroma_spatial, set_chroma_temp;
 
118
  /* internal denoise parameters */
 
119
  gdouble luma_spatial, luma_temp, chroma_spatial, chroma_temp;
 
120
  gboolean quality;
 
121
 
 
122
  /* coefs used in denoising */
 
123
  gint (*coefs)[COEFS_SIZE];
 
124
  /* stores the previous line temporarily (within a plane) */
 
125
  guint *line;
 
126
  /* store the previous *plane*, so several required per frame */
 
127
  gushort *frame[3];
 
128
  /* performs actual denoising depending on quality setting */
 
129
  GstDenoiseFunction denoise_func;
 
130
};
 
131
 
 
132
struct _GstHqdn3dClass
 
133
{
 
134
  GstVideoFilterClass parent_class;
 
135
};
 
136
 
 
137
GST_DEBUG_CATEGORY_STATIC (hqdn3d_debug);
 
138
#define GST_CAT_DEFAULT hqdn3d_debug
 
139
 
 
140
/* signals and args */
 
141
enum
 
142
{
 
143
  /* FILL ME */
 
144
  LAST_SIGNAL
 
145
};
 
146
 
 
147
enum
 
148
{
 
149
  PROP_0,
 
150
  PROP_LUMA_SPATIAL,
 
151
  PROP_CHROMA_SPATIAL,
 
152
  PROP_LUMA_TEMP,
 
153
  PROP_CHROMA_TEMP,
 
154
  PROP_HIGH_QUALITY
 
155
      /* FILL ME */
 
156
};
 
157
 
 
158
#define DEFAULT_LUMA_SPATIAL    4.0
 
159
#define DEFAULT_LUMA_TEMP       6.0
 
160
#define DEFAULT_CHROMA_SPATIAL  3.0
 
161
#define DEFAULT_CHROMA_TEMP   \
 
162
  (DEFAULT_LUMA_TEMP * DEFAULT_CHROMA_SPATIAL / DEFAULT_LUMA_SPATIAL)
 
163
#define HQDN3D_MAX_PARAM        255
 
164
#define DEFAULT_HIGH_QUALITY    TRUE
 
165
 
 
166
/* use these names rather than hardcoded indexes for the coefficient array below */
 
167
enum
 
168
{
 
169
  COEFS_LS_INDEX,
 
170
  COEFS_LT_INDEX,
 
171
  COEFS_CS_INDEX,
 
172
  COEFS_CT_INDEX,
 
173
  COEFS_LAST_INDEX
 
174
};
 
175
 
 
176
 
 
177
static GstElementDetails hqdn3d_details =
 
178
GST_ELEMENT_DETAILS ("Hqdn3d",
 
179
    "Filter/Effect/Video",
 
180
    "High Quality 3D Denoiser",
 
181
    "Mark Nauwelaerts <mnauw@users.sourceforge.net>,\n"
 
182
    "Daniel Moreno, Erik Slagter");
 
183
 
 
184
static GstStaticPadTemplate gst_hqdn3d_src_template =
 
185
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME,
 
186
    GST_PAD_SRC,
 
187
    GST_PAD_ALWAYS,
 
188
    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
 
189
    );
 
190
 
 
191
static GstStaticPadTemplate gst_hqdn3d_sink_template =
 
192
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SINK_NAME,
 
193
    GST_PAD_SINK,
 
194
    GST_PAD_ALWAYS,
 
195
    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
 
196
    );
 
197
 
 
198
static gboolean gst_hqdn3d_hook_caps (GstHqdn3d * btrans, GstCaps * incaps,
 
199
    GstCaps * outcaps);
 
200
static GstFlowReturn gst_hqdn3d_transform_ip (GstBaseTransform * btrans,
 
201
    GstBuffer * in);
 
202
static gboolean gst_hqdn3d_start (GstBaseTransform * btrans);
 
203
static gboolean gst_hqdn3d_stop (GstBaseTransform * btrans);
 
204
 
 
205
static void gst_hqdn3d_set_property (GObject * object, guint prop_id,
 
206
    const GValue * value, GParamSpec * pspec);
 
207
static void gst_hqdn3d_get_property (GObject * object, guint prop_id,
 
208
    GValue * value, GParamSpec * pspec);
 
209
 
 
210
static void gst_hqdn3d_finalize (GObject * object);
 
211
 
 
212
GST_BOILERPLATE (GstHqdn3d, gst_hqdn3d, GstVideoFilter, GST_TYPE_VIDEO_FILTER);
 
213
 
 
214
GST_VIDEO_FILTER_SET_CAPS_BOILERPLATE_FULL (GstHqdn3d, gst_hqdn3d,
 
215
    gst_hqdn3d_hook_caps);
 
216
 
 
217
GST_VIDEO_FILTER_GET_UNIT_SIZE_BOILERPLATE (gst_hqdn3d);
 
218
 
 
219
static void
 
220
gst_hqdn3d_base_init (gpointer g_class)
 
221
{
 
222
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
223
 
 
224
  gst_element_class_set_details (element_class, &hqdn3d_details);
 
225
 
 
226
  gst_element_class_add_pad_template (element_class,
 
227
      gst_static_pad_template_get (&gst_hqdn3d_sink_template));
 
228
  gst_element_class_add_pad_template (element_class,
 
229
      gst_static_pad_template_get (&gst_hqdn3d_src_template));
 
230
}
 
231
 
 
232
static void
 
233
gst_hqdn3d_class_init (GstHqdn3dClass * g_class)
 
234
{
 
235
  GObjectClass *gobject_class;
 
236
  GstBaseTransformClass *trans_class;
 
237
 
 
238
  gobject_class = G_OBJECT_CLASS (g_class);
 
239
  trans_class = GST_BASE_TRANSFORM_CLASS (g_class);
 
240
 
 
241
  GST_DEBUG_CATEGORY_INIT (hqdn3d_debug, "hqdn3d", 0, "hqdn3d");
 
242
 
 
243
  gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_hqdn3d_finalize);
 
244
 
 
245
  gobject_class->set_property = gst_hqdn3d_set_property;
 
246
  gobject_class->get_property = gst_hqdn3d_get_property;
 
247
 
 
248
  g_object_class_install_property (gobject_class, PROP_LUMA_SPATIAL,
 
249
    g_param_spec_double ("luma-spatial", "Luma Spatial",
 
250
        "Spatial Luma Strength (0: use default)",
 
251
        -1, HQDN3D_MAX_PARAM, DEFAULT_LUMA_SPATIAL,
 
252
        G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
253
 
 
254
  g_object_class_install_property (gobject_class, PROP_CHROMA_SPATIAL,
 
255
      g_param_spec_double ("chroma-spatial", "Chroma Spatial",
 
256
        "Spatial Chroma Strength (0: use default)",
 
257
        -1, HQDN3D_MAX_PARAM, DEFAULT_CHROMA_SPATIAL,
 
258
        G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
259
 
 
260
  g_object_class_install_property (gobject_class, PROP_LUMA_TEMP,
 
261
      g_param_spec_double ("luma-temp", "Luma Temporal",
 
262
        "Temporal Luma Strength (0: use default)",
 
263
        -1, HQDN3D_MAX_PARAM, DEFAULT_LUMA_TEMP,
 
264
        G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
265
 
 
266
  g_object_class_install_property (gobject_class, PROP_CHROMA_TEMP,
 
267
      g_param_spec_double ("chroma-temp", "Chroma Temporal",
 
268
        "Temporal Chroma Strength (0: use default)",
 
269
        -1, HQDN3D_MAX_PARAM, DEFAULT_CHROMA_TEMP,
 
270
        G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
271
 
 
272
  g_object_class_install_property (gobject_class, PROP_HIGH_QUALITY,
 
273
        g_param_spec_boolean ("high-quality", "High Quality",
 
274
        "High Quality Denoising (hqdn3d versus denoise3d)",
 
275
        DEFAULT_HIGH_QUALITY, G_PARAM_READWRITE));
 
276
 
 
277
  trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_hqdn3d_set_caps);
 
278
  trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_hqdn3d_get_unit_size);
 
279
  trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_hqdn3d_transform_ip);
 
280
  trans_class->start = GST_DEBUG_FUNCPTR (gst_hqdn3d_start);
 
281
  trans_class->stop = GST_DEBUG_FUNCPTR (gst_hqdn3d_stop);
 
282
}
 
283
 
 
284
static void
 
285
gst_hqdn3d_init (GstHqdn3d * filter, GstHqdn3dClass * g_class)
 
286
{
 
287
  filter->line = NULL;
 
288
  filter->frame[0] = filter->frame[1] = filter->frame[2] = NULL;
 
289
 
 
290
  /* does not depend on any stream specific property,
 
291
   * so can be allocated here */
 
292
  filter->coefs = g_malloc (sizeof(*(filter->coefs)) * COEFS_LAST_INDEX);
 
293
 
 
294
  filter->quality = DEFAULT_HIGH_QUALITY;
 
295
}
 
296
 
 
297
static void
 
298
gst_hqdn3d_finalize (GObject * object)
 
299
{
 
300
  GstHqdn3d *filter = GST_HQDN3D (object);
 
301
 
 
302
  g_free (filter->coefs);
 
303
 
 
304
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
305
}
 
306
 
 
307
static void
 
308
gst_hqdn3d_free (GstHqdn3d * filter)
 
309
{
 
310
  g_free (filter->line);
 
311
  filter->line = NULL;
 
312
  /* hm, just too small to do loop */
 
313
  g_free (filter->frame[0]);
 
314
  g_free (filter->frame[1]);
 
315
  g_free (filter->frame[2]);
 
316
  filter->frame[0] = filter->frame[1] = filter->frame[2] = NULL;
 
317
}
 
318
 
 
319
static void
 
320
gst_hqdn3d_alloc (GstHqdn3d * filter)
 
321
{
 
322
  filter->line = g_malloc (filter->width * sizeof (guint));
 
323
  /* frame will be allocated at the actual transformation time when needed */
 
324
}
 
325
 
 
326
static gboolean
 
327
gst_hqdn3d_hook_caps (GstHqdn3d *filter, GstCaps * incaps,
 
328
    GstCaps * outcaps)
 
329
{
 
330
  gst_hqdn3d_free (filter);
 
331
  gst_hqdn3d_alloc (filter);
 
332
 
 
333
  return TRUE;
 
334
}
 
335
 
 
336
static void
 
337
gst_hqdn3d_precalc_coefs (gint * coefs, double Dist25)
 
338
{
 
339
  int i;
 
340
  double Gamma, Simil, C;
 
341
 
 
342
  Gamma = log(0.25) / log(1.0 - Dist25 / 255.0 - 0.00001);
 
343
 
 
344
  for (i = -256 * 16; i < 256 * 16; i++) {
 
345
    Simil = 1.0 - (i > 0 ? i : -i) / (16 * 255.0);
 
346
    C = pow(Simil, Gamma) * 65536.0 * (double) i / 16.0;
 
347
    coefs[16 * 256 + i] = (C < 0) ? (C - 0.5) : (C + 0.5);
 
348
  }
 
349
}
 
350
 
 
351
static inline guint
 
352
LowPassMul(guint PrevMul, guint CurrMul, gint * Coef)
 
353
{
 
354
//    int dMul= (PrevMul&0xFFFFFF)-(CurrMul&0xFFFFFF);
 
355
  gint dMul = PrevMul - CurrMul;
 
356
  gint d = ( (dMul + 0x10007FF) >> 12);
 
357
  return CurrMul + Coef[d];
 
358
}
 
359
 
 
360
static void
 
361
gst_hqdn3d_denoise (guint8 * Frame, guint * LineAnt, gushort ** FrameAntPtr,
 
362
    gint W, gint H,
 
363
    gint * Horizontal, gint * Vertical, gint * Temporal)
 
364
{
 
365
  gint X, Y;
 
366
  gint sLineOffs = 0;
 
367
  guint PixelAnt;
 
368
  guint PixelDst;
 
369
  gushort* FrameAnt = (*FrameAntPtr);
 
370
 
 
371
  if (!FrameAnt) {
 
372
    (*FrameAntPtr) = FrameAnt = g_malloc (W * H * sizeof (gushort));
 
373
    for (Y = 0; Y < H; Y++){
 
374
      gushort *dst = &FrameAnt[Y * W];
 
375
      guint8 *src = Frame + Y * W;
 
376
      for (X = 0; X < W; X++)
 
377
        dst[X] = src[X] << 8;
 
378
    }
 
379
  }
 
380
 
 
381
  /* First pixel has no left nor top neighbour. Only previous frame */
 
382
  LineAnt[0] = PixelAnt = Frame[0] << 16;
 
383
  PixelDst = LowPassMul (FrameAnt[0] << 8, PixelAnt, Temporal);
 
384
  FrameAnt[0] = ((PixelDst + 0x1000007F) >> 8);
 
385
  Frame[0] = ((PixelDst + 0x10007FFF) >> 16);
 
386
 
 
387
  /* First line has no top neighbour. Only left one for each pixel and
 
388
   * last frame
 
389
   */
 
390
  for (X = 1; X < W; X++){
 
391
    LineAnt[X] = PixelAnt = LowPassMul (PixelAnt, Frame[X] << 16, Horizontal);
 
392
    PixelDst = LowPassMul (FrameAnt[X] << 8, PixelAnt, Temporal);
 
393
    FrameAnt[X] = ((PixelDst + 0x1000007F) >> 8);
 
394
    Frame[X] = ((PixelDst + 0x10007FFF) >> 16);
 
395
  }
 
396
 
 
397
  for (Y = 1; Y < H; Y++){
 
398
    guint PixelAnt;
 
399
    gushort *LinePrev = &FrameAnt[Y*W];
 
400
    sLineOffs += W;
 
401
    /* First pixel on each line doesn't have previous pixel */
 
402
    PixelAnt = Frame[sLineOffs] << 16;
 
403
    LineAnt[0] = LowPassMul(LineAnt[0], PixelAnt, Vertical);
 
404
    PixelDst = LowPassMul(LinePrev[0]<<8, LineAnt[0], Temporal);
 
405
    LinePrev[0] = ((PixelDst + 0x1000007F) >> 8);
 
406
    Frame[sLineOffs] = ((PixelDst + 0x10007FFF) >> 16);
 
407
 
 
408
    for (X = 1; X < W; X++){
 
409
      gint PixelDst;
 
410
      /* The rest are normal */
 
411
      PixelAnt = LowPassMul (PixelAnt, Frame[sLineOffs+X] << 16, Horizontal);
 
412
      LineAnt[X] = LowPassMul (LineAnt[X], PixelAnt, Vertical);
 
413
      PixelDst = LowPassMul (LinePrev[X] << 8, LineAnt[X], Temporal);
 
414
      LinePrev[X] = ((PixelDst + 0x1000007F) >> 8);
 
415
      Frame[sLineOffs+X] = ((PixelDst + 0x10007FFF) >> 16);
 
416
    }
 
417
  }
 
418
}
 
419
 
 
420
/* denoise3d variant */
 
421
 
 
422
static void
 
423
gst_denoise3d_precalc_coefs (gint * ct, double dist25)
 
424
{
 
425
  int i;
 
426
  double gamma, simil, c;
 
427
 
 
428
  gamma = log(0.25) / log(1.0 - dist25 / 255.0);
 
429
 
 
430
  for(i = -256; i <= 255; i++) {
 
431
    simil = 1.0 - (double) ABS (i) / 255.0;
 
432
    c = pow (simil, gamma) * (double) i;
 
433
    ct[256 + i] = (int) ((c < 0) ? (c - 0.5) : (c + 0.5));
 
434
  }
 
435
}
 
436
 
 
437
#define LowPass(prev, curr, coef) (curr + coef[(gint) prev - (gint) curr])
 
438
 
 
439
static void
 
440
gst_denoise3d_denoise (guint8 * frame, guint * lineant, gushort ** frameprevptr,
 
441
      gint w, gint h,
 
442
      gint * horizontal, gint * vertical, gint * temporal)
 
443
{
 
444
  gint x, y;
 
445
  guint8 pixelant;
 
446
  guint8 *lineantptr;
 
447
  guint8 *frameprev = (guint8 *) (*frameprevptr);
 
448
 
 
449
  if (!*frameprevptr)
 
450
    *frameprevptr = g_memdup (frame, w * h);
 
451
  frameprev = (guint8 *) *frameprevptr;
 
452
 
 
453
  lineantptr = (guint8 *) lineant;
 
454
 
 
455
  horizontal += 256;
 
456
  vertical   += 256;
 
457
  temporal   += 256;
 
458
 
 
459
  /* First pixel has no left nor top neighbour, only previous frame */
 
460
  *lineantptr = pixelant = *frame;
 
461
  *frame = *frameprev = LowPass(*frameprev, *lineantptr, temporal);
 
462
  frame++;
 
463
  frameprev++;
 
464
  lineantptr++;
 
465
 
 
466
  /* First line has no top neighbour, only left one for each pixel and last frame */
 
467
  for(x = 1; x < w; x++) {
 
468
    pixelant = LowPass(pixelant, *frame,  horizontal);
 
469
    *lineantptr = pixelant;
 
470
    *frame = *frameprev = LowPass(*frameprev, *lineantptr, temporal);
 
471
    frame++;
 
472
    frameprev++;
 
473
    lineantptr++;
 
474
  }
 
475
 
 
476
  for (y = 1; y < h; y++) {
 
477
    lineantptr = (guint8 *) lineant;
 
478
 
 
479
    /* First pixel on each line doesn't have previous pixel */
 
480
    pixelant = *frame;
 
481
    *lineantptr = LowPass(*lineantptr, pixelant, vertical);
 
482
    *frame = *frameprev = LowPass(*frameprev, *lineantptr, temporal);
 
483
    frame++;
 
484
    frameprev++;
 
485
    lineantptr++;
 
486
 
 
487
    for (x = 1; x < w; x++) {
 
488
      /* The rest is normal */
 
489
      pixelant = LowPass(pixelant, *frame,  horizontal);
 
490
      *lineantptr = LowPass(*lineantptr, pixelant, vertical);
 
491
      *frame = *frameprev = LowPass(*frameprev, *lineantptr, temporal);
 
492
      frame++;
 
493
      frameprev++;
 
494
      lineantptr++;
 
495
    }
 
496
  }
 
497
}
 
498
 
 
499
 
 
500
static GstFlowReturn
 
501
gst_hqdn3d_transform_ip (GstBaseTransform * btrans, GstBuffer * in)
 
502
{
 
503
  GstHqdn3d *filter;
 
504
  guint8 *src, *dest;
 
505
  GstFlowReturn ret = GST_FLOW_OK;
 
506
 
 
507
  gst_object_sync_values (G_OBJECT (btrans), GST_BUFFER_TIMESTAMP (in));
 
508
 
 
509
  filter = GST_HQDN3D (btrans);
 
510
 
 
511
  src = (guint8 *) GST_BUFFER_DATA (in);
 
512
  dest = (guint8 *) GST_BUFFER_DATA (in);
 
513
 
 
514
  gint width = filter->width;
 
515
  gint height = filter->height;
 
516
 
 
517
  /* first run it on the luma plane */
 
518
  if (G_LIKELY (filter->luma_spatial > 0 && filter->luma_temp > 0))
 
519
    filter->denoise_func (src, filter->line, &(filter->frame[0]),
 
520
        GST_VIDEO_I420_Y_ROWSTRIDE (width), height,
 
521
        filter->coefs[COEFS_LS_INDEX], filter->coefs[COEFS_LS_INDEX],
 
522
        filter->coefs[COEFS_LT_INDEX]);
 
523
  /* then on the chroma planes */
 
524
  if (G_LIKELY (filter->chroma_spatial > 0 && filter->chroma_temp > 0)) {
 
525
    filter->denoise_func (src + GST_VIDEO_I420_U_OFFSET (width, height),
 
526
        filter->line, &(filter->frame[1]),
 
527
        GST_VIDEO_I420_U_ROWSTRIDE(width), height / 2,
 
528
        filter->coefs[COEFS_CS_INDEX], filter->coefs[COEFS_CS_INDEX],
 
529
        filter->coefs[COEFS_CT_INDEX]);
 
530
    filter->denoise_func (src + GST_VIDEO_I420_V_OFFSET (width, height),
 
531
        filter->line, &(filter->frame[2]),
 
532
        GST_VIDEO_I420_V_ROWSTRIDE(width), height / 2,
 
533
        filter->coefs[COEFS_CS_INDEX], filter->coefs[COEFS_CS_INDEX],
 
534
        filter->coefs[COEFS_CT_INDEX]);
 
535
  }
 
536
 
 
537
  return ret;
 
538
}
 
539
 
 
540
static void
 
541
gst_hqdn3d_set_params (GstHqdn3d * filter)
 
542
{
 
543
  /* recalculate only the needed params */
 
544
 
 
545
  filter->luma_spatial = filter->set_luma_spatial;
 
546
  if (!filter->luma_spatial)
 
547
    filter->luma_spatial = DEFAULT_LUMA_SPATIAL;
 
548
 
 
549
  filter->chroma_spatial = filter->set_chroma_spatial;
 
550
  if (!filter->chroma_spatial)
 
551
    filter->chroma_spatial = DEFAULT_CHROMA_SPATIAL * filter->luma_spatial /
 
552
        DEFAULT_LUMA_SPATIAL;
 
553
 
 
554
  filter->luma_temp = filter->set_luma_temp;
 
555
  if (!filter->luma_temp)
 
556
    filter->luma_temp = DEFAULT_LUMA_TEMP * filter->luma_spatial /
 
557
        DEFAULT_LUMA_SPATIAL;
 
558
 
 
559
  filter->chroma_temp = filter->set_chroma_temp;
 
560
  if (!filter->chroma_temp)
 
561
    filter->chroma_temp = filter->luma_temp * filter->chroma_spatial /
 
562
        filter->luma_spatial;
 
563
 
 
564
}
 
565
 
 
566
static void gst_hqdn3d_update_props (GstHqdn3d * filter)
 
567
{
 
568
  void (*calc_coefs) (gint *, double);
 
569
 
 
570
  /* are we hqdn3d or denoise3d */
 
571
  if (filter->quality) {
 
572
    calc_coefs = gst_hqdn3d_precalc_coefs;
 
573
  } else {
 
574
    calc_coefs = gst_denoise3d_precalc_coefs;
 
575
  }
 
576
 
 
577
  /* and pre-calculated based on the configured properties */
 
578
  gst_hqdn3d_set_params (filter);
 
579
  calc_coefs (filter->coefs[COEFS_LS_INDEX], filter->luma_spatial);
 
580
  calc_coefs (filter->coefs[COEFS_CS_INDEX], filter->chroma_spatial);
 
581
  calc_coefs (filter->coefs[COEFS_LT_INDEX], filter->luma_temp);
 
582
  calc_coefs (filter->coefs[COEFS_CT_INDEX], filter->chroma_temp);
 
583
}
 
584
 
 
585
static gboolean
 
586
gst_hqdn3d_start (GstBaseTransform * btrans)
 
587
{
 
588
  GstHqdn3d *filter = GST_HQDN3D (btrans);
 
589
 
 
590
  /* let's not change this mid-flight */
 
591
  if (filter->quality) {
 
592
    filter->denoise_func = gst_hqdn3d_denoise;
 
593
  } else {
 
594
    filter->denoise_func = gst_denoise3d_denoise;
 
595
  }
 
596
 
 
597
  gst_hqdn3d_update_props (filter);
 
598
 
 
599
  GST_DEBUG_OBJECT (filter,
 
600
      "starting with luma=%f, luma-temp=%f, chroma=%f, chroma-temp=%f",
 
601
      filter->luma_spatial, filter->luma_temp,
 
602
      filter->chroma_spatial, filter->chroma_temp);
 
603
 
 
604
  return TRUE;
 
605
}
 
606
 
 
607
static gboolean
 
608
gst_hqdn3d_stop (GstBaseTransform * btrans)
 
609
{
 
610
  GstHqdn3d *filter = GST_HQDN3D (btrans);
 
611
 
 
612
  gst_hqdn3d_free (filter);
 
613
 
 
614
  return TRUE;
 
615
}
 
616
 
 
617
static void
 
618
gst_hqdn3d_set_property (GObject * object, guint prop_id,
 
619
    const GValue * value, GParamSpec * pspec)
 
620
{
 
621
  GstHqdn3d *src;
 
622
  gboolean changed = FALSE;
 
623
  gdouble tmp;
 
624
 
 
625
  g_return_if_fail (GST_IS_HQDN3D (object));
 
626
  src = GST_HQDN3D (object);
 
627
 
 
628
  switch (prop_id) {
 
629
    case PROP_LUMA_SPATIAL:
 
630
      tmp = g_value_get_double (value);
 
631
      if (tmp != src->set_luma_spatial) {
 
632
        src->set_luma_spatial = tmp;
 
633
        changed = TRUE;
 
634
      }
 
635
      break;
 
636
    case PROP_CHROMA_SPATIAL:
 
637
      tmp = g_value_get_double (value);
 
638
      if (tmp != src->set_chroma_spatial) {
 
639
        src->set_chroma_spatial = tmp;
 
640
        changed = TRUE;
 
641
      }
 
642
      break;
 
643
    case PROP_LUMA_TEMP:
 
644
      tmp = g_value_get_double (value);
 
645
      if (tmp != src->set_luma_temp) {
 
646
        src->set_luma_temp = tmp;
 
647
        changed = TRUE;
 
648
      }
 
649
      break;
 
650
    case PROP_CHROMA_TEMP:
 
651
      tmp = g_value_get_double (value);
 
652
      if (tmp != src->set_chroma_temp) {
 
653
        src->set_chroma_temp = tmp;
 
654
        changed = TRUE;
 
655
      }
 
656
      break;
 
657
    case PROP_HIGH_QUALITY:
 
658
      src->quality = g_value_get_boolean (value);
 
659
      break;
 
660
    default:
 
661
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
662
      break;
 
663
  }
 
664
 
 
665
  if (changed)
 
666
    gst_hqdn3d_update_props (src);
 
667
}
 
668
 
 
669
static void
 
670
gst_hqdn3d_get_property (GObject * object, guint prop_id, GValue * value,
 
671
    GParamSpec * pspec)
 
672
{
 
673
  GstHqdn3d *src;
 
674
 
 
675
  g_return_if_fail (GST_IS_HQDN3D (object));
 
676
  src = GST_HQDN3D (object);
 
677
 
 
678
  switch (prop_id) {
 
679
    case PROP_LUMA_SPATIAL:
 
680
      g_value_set_double (value, src->luma_spatial);
 
681
      break;
 
682
    case PROP_CHROMA_SPATIAL:
 
683
      g_value_set_double (value, src->chroma_spatial);
 
684
      break;
 
685
    case PROP_LUMA_TEMP:
 
686
      g_value_set_double (value, src->luma_temp);
 
687
      break;
 
688
    case PROP_CHROMA_TEMP:
 
689
      g_value_set_double (value, src->chroma_temp);
 
690
      break;
 
691
    case PROP_HIGH_QUALITY:
 
692
      g_value_set_boolean (value, src->quality);
 
693
      break;
 
694
    default:
 
695
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
696
      break;
 
697
  }
 
698
}