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

« back to all changes in this revision

Viewing changes to gst/virtualdub/gstkerneldeint.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 Element
 
2
 * Copyright (C) 2006 Mark Nauwelaerts <mnauw@users.sourceforge.net>
 
3
 *
 
4
 * Avisynth filter plugin:
 
5
 * Copyright (C) 2003 Donald A. Graft
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02110-1307  USA
 
20
 */
 
21
 
 
22
/**
 
23
 * SECTION:element-kerneldeint
 
24
 *
 
25
 * <refsect2>
 
26
 * <para>
 
27
 * [based on Avisynth filter documentation]
 
28
 * </para>
 
29
 * <para>
 
30
 * This filter deinterlaces using a kernel approach.
 
31
 * It gives greatly improved vertical resolution in deinterlaced areas
 
32
 * compared to simple field discarding.
 
33
 * </para>
 
34
 * <para>
 
35
 * If you set the <link linkend="GstKernelDeint--threshold">threshold</link>
 
36
 * to 0, you can get totally artifact free results (due to lack of thresholding)
 
37
 * but with much less loss of vertical resolution than simple field discarding.
 
38
 * For optimal results, however, set a motion threshold that allows static
 
39
 * areas of the picture to be passed through. In this mode, the kernel-based
 
40
 * deinterlacing of the moving areas preserves their vertical resolution compared
 
41
 * to simple interpolation.
 
42
 * </para>
 
43
 * <para>
 
44
 * This filter assumes that top field is first.  If not, use a filter (e.g. fields)
 
45
 * to swap them.  Note that whether the top field is indeed first can be verified
 
46
 * by separating fields (using e.g. fields) and verifying that motion is progressive
 
47
 * (and not jumping back and forth).
 
48
 * </para>
 
49
 * <para>
 
50
 * The <link linkend="GstKernelDeint--threshold">threshold</link> parameter
 
51
 * defines the "motion" thresold. Moving areas are kernel-deinterlaced while
 
52
 * non-moving areas are passed through.
 
53
 * Use the <link linkend="GstKernelDeint--map">map</link> parameter to tweak
 
54
 * the threshold parameter so that just the combed areas of the frame are
 
55
 * deinterlaced.
 
56
 * </para>
 
57
 * <para>
 
58
 * <link linkend="GstKernelDeint--sharp">sharp</link>, when set to true,
 
59
 * selects a kernel that provides better vertical resolution and performs
 
60
 * some sharpening of the video. For less sharpening but also less vertical
 
61
 * resolution, set this parameter to false.
 
62
 * </para>
 
63
 * <para>
 
64
 * <link linkend="GstKernelDeint--two-way">two-way</link>, when set to true,
 
65
 * selects a kernel that includes both the previous and the following fields
 
66
 * for deinterlacing. When set to false, the kernel includes only the previous
 
67
 * field. The latter one-way kernel is faster, crisper, and gives less blending
 
68
 * (this last advantage makes the filter perform better on anime).
 
69
 * </para>
 
70
 * <para>
 
71
 * <link linkend="GstKernelDeint--map">map</link>, when set to true, shows
 
72
 * the areas that are "moving" as determined by the
 
73
 * <link linkend="GstKernelDeint--threshold">threshold</link> parameter
 
74
 * and which will be kernel-deinterlaced.
 
75
 * </para>
 
76
 * <title>History</title>
 
77
 * <para>
 
78
 * <itemizedlist>
 
79
 * <listitem>
 
80
 * Avisynth kerndeint filter [Donald A. Graft]
 
81
 * </listitem>
 
82
 * <listitem>
 
83
 * Also available in mplayer (kerndeint filter)
 
84
 * </listitem>
 
85
 * <listitem>
 
86
 * Also available in avidemux (kernel deinterlacer)
 
87
 * </listitem>
 
88
 * </itemizedlist>
 
89
 * </para>
 
90
 * </refsect2>
 
91
 */
 
92
 
 
93
 
 
94
#ifdef HAVE_CONFIG_H
 
95
#include "config.h"
 
96
#endif
 
97
 
 
98
#include "plugin-vd.h"
 
99
 
 
100
#include <string.h>
 
101
#include <stdlib.h>
 
102
 
 
103
 
 
104
#define GST_TYPE_KERNEL_DEINT \
 
105
  (gst_kernel_deint_get_type())
 
106
#define GST_KERNEL_DEINT(obj) \
 
107
  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_KERNEL_DEINT,GstKernelDeint))
 
108
#define GST_KERNEL_DEINT_CLASS(klass) \
 
109
  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_KERNEL_DEINT,GstKernelDeintClass))
 
110
#define GST_IS_KERNEL_DEINT(obj) \
 
111
  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_KERNEL_DEINT))
 
112
#define GST_IS_KERNEL_DEINT_CLASS(klass) \
 
113
  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_KERNEL_DEINT))
 
114
 
 
115
 
 
116
typedef struct _GstKernelDeint GstKernelDeint;
 
117
typedef struct _GstKernelDeintClass GstKernelDeintClass;
 
118
 
 
119
struct _GstKernelDeint
 
120
{
 
121
  GstVideoFilter videofilter;
 
122
 
 
123
  gint width, height;
 
124
 
 
125
  /* properties */
 
126
  guint threshold;
 
127
  gboolean sharp, two_way, map;
 
128
 
 
129
  /* image type */
 
130
  guint img;
 
131
 
 
132
  /* previous buffer */
 
133
  GstBuffer *prev;
 
134
};
 
135
 
 
136
 
 
137
struct _GstKernelDeintClass
 
138
{
 
139
  GstVideoFilterClass parent_class;
 
140
};
 
141
 
 
142
GST_DEBUG_CATEGORY_STATIC (kernel_deint_debug);
 
143
#define GST_CAT_DEFAULT kernel_deint_debug
 
144
 
 
145
/* signals and args */
 
146
enum
 
147
{
 
148
  /* FILL ME */
 
149
  LAST_SIGNAL
 
150
};
 
151
 
 
152
enum
 
153
{
 
154
  PROP_0,
 
155
  PROP_THRESHOLD,
 
156
  PROP_SHARP,
 
157
  PROP_TWO_WAY,
 
158
  PROP_MAP
 
159
     /* FILL ME */
 
160
};
 
161
 
 
162
#define MIN_THRESHOLD       0
 
163
#define MAX_THRESHOLD      100
 
164
#define DEFAULT_THRESHOLD   10
 
165
#define DEFAULT_SHARP      FALSE
 
166
#define DEFAULT_TWO_WAY    FALSE
 
167
#define DEFAULT_MAP        FALSE
 
168
 
 
169
enum
 
170
{
 
171
  IMGFMT_YUV,
 
172
  IMGFMT_YUY2,
 
173
  IMGFMT_RGB
 
174
};
 
175
 
 
176
static GstElementDetails kernel_deint_details =
 
177
GST_ELEMENT_DETAILS ("KernelDeint",
 
178
    "Filter/Effect/Video",
 
179
    "Adaptive kernel deinterlacer",
 
180
    "Mark Nauwelaerts <mnauw@users.sourceforge.net>,\n"
 
181
    "Donald A. Graft");
 
182
 
 
183
static GstStaticPadTemplate gst_kernel_deint_src_template =
 
184
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SRC_NAME,
 
185
    GST_PAD_SRC,
 
186
    GST_PAD_ALWAYS,
 
187
    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12, YUY2, YUYV, YVYU }") " ; "
 
188
        GST_VIDEO_CAPS_RGBx " ; " GST_VIDEO_CAPS_BGRx " ; "
 
189
        GST_VIDEO_CAPS_xRGB " ; " GST_VIDEO_CAPS_xBGR)
 
190
    );
 
191
 
 
192
static GstStaticPadTemplate gst_kernel_deint_sink_template =
 
193
GST_STATIC_PAD_TEMPLATE (GST_BASE_TRANSFORM_SINK_NAME,
 
194
    GST_PAD_SINK,
 
195
    GST_PAD_ALWAYS,
 
196
    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12, YUY2, YUYV, YVYU }") " ; "
 
197
        GST_VIDEO_CAPS_RGBx " ; " GST_VIDEO_CAPS_BGRx " ; "
 
198
        GST_VIDEO_CAPS_xRGB " ; " GST_VIDEO_CAPS_xBGR)
 
199
    );
 
200
 
 
201
static gboolean gst_kernel_deint_hook_caps (GstKernelDeint * filter,
 
202
    GstCaps * incaps, GstCaps * outcaps);
 
203
static GstFlowReturn gst_kernel_deint_transform (GstBaseTransform * btrans,
 
204
    GstBuffer * in, GstBuffer * out);
 
205
static gboolean gst_kernel_deint_start (GstBaseTransform * btrans);
 
206
static gboolean gst_kernel_deint_stop (GstBaseTransform * btrans);
 
207
 
 
208
static void gst_kernel_deint_set_property (GObject * object, guint prop_id,
 
209
    const GValue * value, GParamSpec * pspec);
 
210
static void gst_kernel_deint_get_property (GObject * object, guint prop_id,
 
211
    GValue * value, GParamSpec * pspec);
 
212
 
 
213
GST_BOILERPLATE (GstKernelDeint, gst_kernel_deint, GstVideoFilter, GST_TYPE_VIDEO_FILTER);
 
214
 
 
215
GST_VIDEO_FILTER_SET_CAPS_BOILERPLATE_FULL (GstKernelDeint, gst_kernel_deint,
 
216
    gst_kernel_deint_hook_caps);
 
217
 
 
218
GST_VIDEO_FILTER_GET_UNIT_SIZE_BOILERPLATE (gst_kernel_deint);
 
219
 
 
220
static void
 
221
gst_kernel_deint_base_init (gpointer g_class)
 
222
{
 
223
  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
 
224
 
 
225
  gst_element_class_set_details (element_class, &kernel_deint_details);
 
226
 
 
227
  gst_element_class_add_pad_template (element_class,
 
228
      gst_static_pad_template_get (&gst_kernel_deint_sink_template));
 
229
  gst_element_class_add_pad_template (element_class,
 
230
      gst_static_pad_template_get (&gst_kernel_deint_src_template));
 
231
}
 
232
 
 
233
static void
 
234
gst_kernel_deint_class_init (GstKernelDeintClass * g_class)
 
235
{
 
236
  GObjectClass *gobject_class;
 
237
  GstBaseTransformClass *trans_class;
 
238
 
 
239
  gobject_class = G_OBJECT_CLASS (g_class);
 
240
  trans_class = GST_BASE_TRANSFORM_CLASS (g_class);
 
241
 
 
242
  GST_DEBUG_CATEGORY_INIT (kernel_deint_debug, "kerneldeint", 0, "kerneldeint");
 
243
 
 
244
  gobject_class->set_property = gst_kernel_deint_set_property;
 
245
  gobject_class->get_property = gst_kernel_deint_get_property;
 
246
 
 
247
  g_object_class_install_property (gobject_class, PROP_THRESHOLD,
 
248
      g_param_spec_uint ("threshold", "Threshold",
 
249
          "Threshold",
 
250
          MIN_THRESHOLD, MAX_THRESHOLD, DEFAULT_THRESHOLD,
 
251
          G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
252
 
 
253
  g_object_class_install_property (gobject_class, PROP_SHARP,
 
254
      g_param_spec_boolean ("sharp", "Sharp",
 
255
          "Enable/disable additional sharping",
 
256
          DEFAULT_SHARP, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
257
 
 
258
  g_object_class_install_property (gobject_class, PROP_TWO_WAY,
 
259
      g_param_spec_boolean ("two-way", "Two-Way",
 
260
          "Enable/disable two-way sharpening",
 
261
          DEFAULT_TWO_WAY, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
262
 
 
263
  g_object_class_install_property (gobject_class, PROP_MAP,
 
264
      g_param_spec_boolean ("map", "Map",
 
265
          "Paint/ignore pixels exceeding threshold",
 
266
          DEFAULT_MAP, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
 
267
 
 
268
  trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_kernel_deint_set_caps);
 
269
  trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_kernel_deint_get_unit_size);
 
270
  trans_class->transform = GST_DEBUG_FUNCPTR (gst_kernel_deint_transform);
 
271
  trans_class->start = GST_DEBUG_FUNCPTR (gst_kernel_deint_start);
 
272
  trans_class->stop = GST_DEBUG_FUNCPTR (gst_kernel_deint_stop);
 
273
}
 
274
 
 
275
static void
 
276
gst_kernel_deint_init (GstKernelDeint * filter, GstKernelDeintClass * g_class)
 
277
{
 
278
  filter->threshold = DEFAULT_THRESHOLD;
 
279
  filter->sharp = DEFAULT_SHARP;
 
280
  filter->two_way = DEFAULT_TWO_WAY;
 
281
  filter->map = DEFAULT_MAP;
 
282
}
 
283
 
 
284
static void
 
285
gst_kernel_deint_free (GstKernelDeint * filter)
 
286
{
 
287
  if (filter->prev)
 
288
    gst_buffer_unref (filter->prev);
 
289
  filter->prev = NULL;
 
290
}
 
291
 
 
292
static gboolean
 
293
gst_kernel_deint_hook_caps (GstKernelDeint * filter, GstCaps * incaps,
 
294
    GstCaps * outcaps)
 
295
{
 
296
  GstStructure *structure;
 
297
  gboolean ret = FALSE;
 
298
 
 
299
  structure = gst_caps_get_structure (incaps, 0);
 
300
 
 
301
  gst_kernel_deint_free (filter);
 
302
  if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
 
303
    ret = TRUE;
 
304
    filter->img = IMGFMT_RGB;
 
305
  } else {
 
306
    guint32 fourcc;
 
307
 
 
308
    if ((ret = gst_structure_get_fourcc (structure, "format", &fourcc)))
 
309
    switch (fourcc) {
 
310
      case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
 
311
      case GST_MAKE_FOURCC ('Y', 'Y', 'Y', 'V'):
 
312
      case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
 
313
        filter->img = IMGFMT_YUY2;
 
314
        break;
 
315
      case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
 
316
      case GST_MAKE_FOURCC ('I', '4', '2', '0'):
 
317
      case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
 
318
      default:
 
319
        filter->img = IMGFMT_YUV;
 
320
    }
 
321
  }
 
322
 
 
323
  return ret;
 
324
}
 
325
 
 
326
 
 
327
#define PROGRESSIVE  0x00000001
 
328
 
 
329
static void
 
330
gst_kernel_deint_do_deint (GstKernelDeint * filter, guint8 * src, guint8 * dest,
 
331
    guint8 * prev)
 
332
{
 
333
  const guint8 *srcp, *prvp,*prvp_saved, *prvpp, *prvpn, *prvppp, *prvpnn, *prvp4p, *prvp4n;
 
334
  const guint8 *srcp_saved;
 
335
  const guint8 *srcpp, *srcppp, *srcpn, *srcpnn, *srcp3p, *srcp3n, *srcp4p, *srcp4n;
 
336
  guint8 *dstp;
 
337
  guint8 *dstp_saved;
 
338
 
 
339
  int src_pitch;
 
340
  int dst_pitch;
 
341
  int w;
 
342
  int h;
 
343
  int x, y, z;
 
344
  int val, hi, lo;
 
345
  double valf;
 
346
 
 
347
  guint32 pitch, height, width;
 
348
  guint32 offset = 0;
 
349
 
 
350
  guint32 order, threshold;
 
351
  guint8  sharp, twoway, map;
 
352
 
 
353
  height = filter->height;
 
354
  width = filter->width;
 
355
 
 
356
  /* always considered top-field first */
 
357
  order = 1;
 
358
  threshold = filter->threshold;
 
359
  sharp = filter->sharp;
 
360
  twoway = filter->two_way;
 
361
  map = filter->map;
 
362
 
 
363
  for (z = 0; z < (filter->img == IMGFMT_YUV ? 3 : 1); z++) {
 
364
 
 
365
    switch(z) {
 
366
      case 0:
 
367
        offset = 0;
 
368
        switch (filter->img) {
 
369
          case IMGFMT_YUV:
 
370
            pitch = GST_VIDEO_I420_Y_ROWSTRIDE (width);
 
371
            break;
 
372
          case IMGFMT_RGB:
 
373
            pitch = 4 * width;
 
374
            break;
 
375
          default:
 
376
            pitch = 2 * width;
 
377
        }
 
378
        break;
 
379
      case 1:
 
380
        offset = GST_VIDEO_I420_U_OFFSET (width, height);
 
381
        pitch = GST_VIDEO_I420_U_ROWSTRIDE (width);
 
382
        break;
 
383
      case 2:
 
384
        offset = GST_VIDEO_I420_V_OFFSET (width, height);
 
385
        pitch = GST_VIDEO_I420_V_ROWSTRIDE (width);
 
386
        break;
 
387
      default:
 
388
        g_assert_not_reached ();
 
389
        break;
 
390
    }
 
391
    srcp = srcp_saved = src + offset;
 
392
    dstp = dstp_saved = dest + offset;
 
393
    prvp_saved = prvp = prev + offset;
 
394
 
 
395
    src_pitch = pitch;
 
396
    dst_pitch = pitch;
 
397
 
 
398
    w = pitch;
 
399
    h = height;
 
400
    if (z) {
 
401
      h >>= 1;
 
402
    }
 
403
 
 
404
    srcp = srcp_saved + (1 - order) * src_pitch;
 
405
    dstp = dstp_saved + (1 - order) * dst_pitch;
 
406
    for (y = 0; y < h; y += 2) {
 
407
      oil_memcpy (dstp, srcp, w);
 
408
      srcp += 2 * src_pitch;
 
409
      dstp += 2 * dst_pitch;
 
410
    }
 
411
 
 
412
    /* Copy through the lines that will be missed below. */
 
413
    oil_memcpy (dstp_saved + order * dst_pitch,
 
414
        srcp_saved + (1 - order) * src_pitch, w);
 
415
    oil_memcpy (dstp_saved + (2 + order) * dst_pitch,
 
416
        srcp_saved + (3 - order) * src_pitch, w);
 
417
    oil_memcpy (dstp_saved + (h - 2 + order) * dst_pitch,
 
418
        srcp_saved + (h - 1 - order) * src_pitch, w);
 
419
    oil_memcpy (dstp_saved + (h - 4 + order) * dst_pitch,
 
420
        srcp_saved + (h - 3 - order) * src_pitch, w);
 
421
 
 
422
    /* For the other field choose adaptively between using the previous field
 
423
     * or the interpolant from the current field. */
 
424
    prvp = prvp_saved +  5 * src_pitch - (1 - order) * src_pitch;
 
425
    prvpp = prvp - src_pitch;
 
426
    prvppp = prvp - 2 * src_pitch;
 
427
    prvp4p = prvp - 4 * src_pitch;
 
428
    prvpn = prvp + src_pitch;
 
429
    prvpnn = prvp + 2 * src_pitch;
 
430
    prvp4n = prvp + 4 * src_pitch;
 
431
    srcp = srcp_saved + 5 * src_pitch - (1 - order) * src_pitch;
 
432
    srcpp = srcp - src_pitch;
 
433
    srcppp = srcp - 2 * src_pitch;
 
434
    srcp3p = srcp - 3 * src_pitch;
 
435
    srcp4p = srcp - 4 * src_pitch;
 
436
    srcpn = srcp + src_pitch;
 
437
    srcpnn = srcp + 2 * src_pitch;
 
438
    srcp3n = srcp + 3 * src_pitch;
 
439
    srcp4n = srcp + 4 * src_pitch;
 
440
    dstp =  dstp_saved  + 5 * dst_pitch - (1 - order) * dst_pitch;
 
441
    for (y = 5 - (1 - order); y <= h - 5 - (1 - order); y+=2) {
 
442
      for (x = 0; x < w; x++) {
 
443
        if ((threshold == 0) ||
 
444
             (abs ((int) prvp[x] - (int) srcp[x]) > threshold) ||
 
445
             (abs ((int) prvpp[x] - (int) srcpp[x]) > threshold) ||
 
446
             (abs ((int) prvpn[x] - (int) srcpn[x]) > threshold)) {
 
447
          if (map == TRUE) {
 
448
            switch (filter->img) {
 
449
              case IMGFMT_YUV:
 
450
                if (z == 0)
 
451
                  dstp[x] = 235;
 
452
                else
 
453
                  dstp[x] = 128;
 
454
                break;
 
455
              case IMGFMT_RGB: {
 
456
                int g = x & ~3;
 
457
 
 
458
                dstp[g++] = 255;
 
459
                dstp[g++] = 255;
 
460
                dstp[g++] = 255;
 
461
                dstp[g] = 255;
 
462
                x = g;
 
463
                break;
 
464
                }
 
465
              default: {
 
466
                int g = x & ~3;
 
467
 
 
468
                dstp[g++] = 235;
 
469
                dstp[g++] = 128;
 
470
                dstp[g++] = 235;
 
471
                dstp[g] = 128;
 
472
                x = g;
 
473
                break;
 
474
              }
 
475
            }
 
476
          } else {
 
477
 
 
478
            switch (filter->img) {
 
479
              case IMGFMT_YUV:
 
480
                hi = (z == 0) ? 235 : 240;
 
481
                lo = 16;
 
482
                break;
 
483
              case IMGFMT_RGB:
 
484
                hi = 255;
 
485
                lo = 0;
 
486
                break;
 
487
              default:
 
488
                hi = (x & 1) ? 240 : 235;
 
489
                lo = 16;
 
490
                break;
 
491
            }
 
492
 
 
493
            if (sharp == TRUE) {
 
494
              if (twoway == TRUE)
 
495
                valf = + 0.526*((int) srcpp[x] +
 
496
                    (int) srcpn[x])
 
497
                    + 0.170 * ((int) srcp[x] + (int) prvp[x])
 
498
                    - 0.116 * ((int) srcppp[x] +
 
499
                    (int) srcpnn[x] + (int) prvppp[x] +
 
500
                    (int) prvpnn[x])
 
501
                    - 0.026 * ((int) srcp3p[x] +
 
502
                    (int) srcp3n[x])
 
503
                    + 0.031 * ((int) srcp4p[x] +
 
504
                    (int) srcp4n[x] + (int) prvp4p[x] +
 
505
                    (int) prvp4n[x]);
 
506
              else
 
507
                valf = + 0.526 * ((int) srcpp[x] +
 
508
                    (int) srcpn[x])
 
509
                    + 0.170 * ((int) prvp[x])
 
510
                    - 0.116 * ((int) prvppp[x] +
 
511
                    (int) prvpnn[x])
 
512
                    - 0.026 * ((int) srcp3p[x] +
 
513
                    (int) srcp3n[x])
 
514
                    + 0.031 * ((int) prvp4p[x] +
 
515
                    (int) prvp4p[x]);
 
516
              if (valf > hi)
 
517
                valf = hi;
 
518
              else
 
519
                if (valf < lo)
 
520
                  valf = lo;
 
521
              dstp[x] = (int) valf;
 
522
            }
 
523
            else {
 
524
              if (twoway == TRUE)
 
525
                val = (8 * ((int) srcpp[x] + (int) srcpn[x]) +
 
526
                    2 * ((int) srcp[x] + (int) prvp[x]) -
 
527
                    (int) (srcppp[x]) -
 
528
                    (int) (srcpnn[x]) -
 
529
                    (int) (prvppp[x]) -
 
530
                    (int) (prvpnn[x])) >> 4;
 
531
              else
 
532
                val = (8 * ((int) srcpp[x] + (int) srcpn[x]) +
 
533
                    2 * ((int) prvp[x]) -
 
534
                    (int) (prvppp[x]) -
 
535
                    (int) (prvpnn[x])) >> 4;
 
536
              if (val > hi)
 
537
                val = hi;
 
538
              else
 
539
                if (val < lo)
 
540
                  val = lo;
 
541
              dstp[x] = (int) val;
 
542
            }
 
543
          }
 
544
        }
 
545
        else {
 
546
          dstp[x] = srcp[x];
 
547
        }
 
548
      }
 
549
      prvp  += 2 * src_pitch;
 
550
      prvpp  += 2 * src_pitch;
 
551
      prvppp  += 2 * src_pitch;
 
552
      prvpn  += 2 * src_pitch;
 
553
      prvpnn  += 2 * src_pitch;
 
554
      prvp4p  += 2 * src_pitch;
 
555
      prvp4n  += 2 * src_pitch;
 
556
      srcp  += 2 * src_pitch;
 
557
      srcpp += 2 * src_pitch;
 
558
      srcppp += 2 * src_pitch;
 
559
      srcp3p += 2 * src_pitch;
 
560
      srcp4p += 2 * src_pitch;
 
561
      srcpn += 2 * src_pitch;
 
562
      srcpnn += 2 * src_pitch;
 
563
      srcp3n += 2 * src_pitch;
 
564
      srcp4n += 2 * src_pitch;
 
565
      dstp  += 2 * dst_pitch;
 
566
    }
 
567
  }
 
568
}
 
569
 
 
570
static GstFlowReturn
 
571
gst_kernel_deint_transform (GstBaseTransform * btrans, GstBuffer * in, GstBuffer * out)
 
572
{
 
573
  GstKernelDeint *filter = GST_KERNEL_DEINT (btrans);
 
574
 
 
575
  gst_object_sync_values (G_OBJECT (btrans), GST_BUFFER_TIMESTAMP (in));
 
576
 
 
577
  if (filter->prev)
 
578
   gst_kernel_deint_do_deint (filter, GST_BUFFER_DATA (in), GST_BUFFER_DATA (out),
 
579
        GST_BUFFER_DATA (filter->prev));
 
580
 
 
581
  /* get rid of old */
 
582
  if (filter->prev)
 
583
    gst_buffer_unref (filter->prev);
 
584
  /* and make sure the current one sticks around */
 
585
  gst_buffer_ref (in);
 
586
  filter->prev = in;
 
587
 
 
588
  return GST_FLOW_OK;
 
589
}
 
590
 
 
591
 
 
592
static gboolean
 
593
gst_kernel_deint_start (GstBaseTransform * btrans)
 
594
{
 
595
  return TRUE;
 
596
}
 
597
 
 
598
static gboolean
 
599
gst_kernel_deint_stop (GstBaseTransform * btrans)
 
600
{
 
601
  GstKernelDeint *filter;
 
602
 
 
603
  filter = GST_KERNEL_DEINT (btrans);
 
604
 
 
605
  gst_kernel_deint_free (filter);
 
606
 
 
607
  return TRUE;
 
608
}
 
609
 
 
610
static void
 
611
gst_kernel_deint_set_property (GObject * object, guint prop_id,
 
612
    const GValue * value, GParamSpec * pspec)
 
613
{
 
614
  GstKernelDeint *src;
 
615
 
 
616
  g_return_if_fail (GST_IS_KERNEL_DEINT (object));
 
617
  src = GST_KERNEL_DEINT (object);
 
618
 
 
619
  switch (prop_id) {
 
620
    case PROP_THRESHOLD:
 
621
      src->threshold = g_value_get_uint (value);
 
622
      break;
 
623
    case PROP_SHARP:
 
624
      src->sharp = g_value_get_boolean (value);
 
625
      break;
 
626
    case PROP_TWO_WAY:
 
627
      src->two_way = g_value_get_boolean (value);
 
628
      break;
 
629
    case PROP_MAP:
 
630
      src->map = g_value_get_boolean (value);
 
631
      break;
 
632
    default:
 
633
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
634
      break;
 
635
  }
 
636
}
 
637
 
 
638
static void
 
639
gst_kernel_deint_get_property (GObject * object, guint prop_id, GValue * value,
 
640
    GParamSpec * pspec)
 
641
{
 
642
  GstKernelDeint *src;
 
643
 
 
644
  g_return_if_fail (GST_IS_KERNEL_DEINT (object));
 
645
  src = GST_KERNEL_DEINT (object);
 
646
 
 
647
  switch (prop_id) {
 
648
    case PROP_THRESHOLD:
 
649
      g_value_set_uint (value, src->threshold);
 
650
      break;
 
651
    case PROP_SHARP:
 
652
      g_value_set_boolean (value, src->sharp);
 
653
      break;
 
654
    case PROP_TWO_WAY:
 
655
      g_value_set_boolean (value, src->two_way);
 
656
      break;
 
657
    case PROP_MAP:
 
658
      g_value_set_boolean (value, src->map);
 
659
      break;
 
660
    default:
 
661
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
662
      break;
 
663
  }
 
664
}