~ubuntu-branches/ubuntu/quantal/gst-plugins-bad-multiverse0.10/quantal

« back to all changes in this revision

Viewing changes to gst/deinterlace2/tvtime/greedyh.c

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2009-02-23 02:23:58 UTC
  • mfrom: (1.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20090223022358-9yhx5izc7dz60yc8
Tags: 0.10.10-0ubuntu1
* New upstream release.
* debian/rules
  - Disable some plugins which get built by default but we do not ship in 
    multiverse package.
  - Do not build docs as there is no multiverse-doc package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * GStreamer
 
4
 * Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
 
5
 * Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Library General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library 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 GNU
 
15
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Library General Public
 
18
 * License along with this library; if not, write to the
 
19
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
20
 * Boston, MA 02111-1307, USA.
 
21
 */
 
22
 
 
23
/*
 
24
 * Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs.
 
25
 * See: http://bugzilla.gnome.org/show_bug.cgi?id=163578
 
26
 */
 
27
 
 
28
#ifdef HAVE_CONFIG_H
 
29
# include "config.h"
 
30
#endif
 
31
 
 
32
#include "greedyhmacros.h"
 
33
 
 
34
#include <stdlib.h>
 
35
#include "_stdint.h"
 
36
#include <string.h>
 
37
 
 
38
#include "gst/gst.h"
 
39
#include "plugins.h"
 
40
#include "gstdeinterlace2.h"
 
41
 
 
42
#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_H    (gst_deinterlace_method_greedy_h_get_type ())
 
43
#define GST_IS_DEINTERLACE_METHOD_GREEDY_H(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
 
44
#define GST_IS_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
 
45
#define GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass))
 
46
#define GST_DEINTERLACE_METHOD_GREEDY_H(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyH))
 
47
#define GST_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass))
 
48
#define GST_DEINTERLACE_METHOD_GREEDY_H_CAST(obj)       ((GstDeinterlaceMethodGreedyH*)(obj))
 
49
 
 
50
GType gst_deinterlace_method_greedy_h_get_type (void);
 
51
 
 
52
typedef struct
 
53
{
 
54
  GstDeinterlaceMethod parent;
 
55
 
 
56
  guint max_comb, motion_threshold, motion_sense;
 
57
} GstDeinterlaceMethodGreedyH;
 
58
 
 
59
typedef struct
 
60
{
 
61
  GstDeinterlaceMethodClass parent_class;
 
62
  void (*scanline) (GstDeinterlaceMethodGreedyH * self, uint8_t * L2,
 
63
      uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size);
 
64
} GstDeinterlaceMethodGreedyHClass;
 
65
 
 
66
void
 
67
greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2,
 
68
    uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size)
 
69
{
 
70
  int Pos;
 
71
  uint8_t l1_l, l1_1_l, l3_l, l3_1_l;
 
72
  uint8_t l1_c, l1_1_c, l3_c, l3_1_c;
 
73
  uint8_t avg_l, avg_c, avg_l_1, avg_c_1;
 
74
  uint8_t avg_l__1 = 0, avg_c__1 = 0;
 
75
  uint8_t avg_s_l, avg_s_c;
 
76
  uint8_t avg_sc_l, avg_sc_c;
 
77
  uint8_t best_l, best_c;
 
78
  uint16_t mov_l;
 
79
  uint8_t out_l, out_c;
 
80
  uint8_t l2_l, l2_c, lp2_l, lp2_c;
 
81
  uint8_t l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff;
 
82
  uint8_t min_l, min_c, max_l, max_c;
 
83
  guint max_comb = self->max_comb;
 
84
  guint motion_sense = self->motion_sense;
 
85
  guint motion_threshold = self->motion_threshold;
 
86
 
 
87
  for (Pos = 0; Pos < size; Pos += 2) {
 
88
    l1_l = L1[0];
 
89
    l1_c = L1[1];
 
90
    l3_l = L3[0];
 
91
    l3_c = L3[1];
 
92
 
 
93
    if (Pos == size - 1) {
 
94
      l1_1_l = l1_l;
 
95
      l1_1_c = l1_c;
 
96
      l3_1_l = l3_l;
 
97
      l3_1_c = l3_c;
 
98
    } else {
 
99
      l1_1_l = L1[2];
 
100
      l1_1_c = L1[3];
 
101
      l3_1_l = L3[2];
 
102
      l3_1_c = L3[3];
 
103
    }
 
104
 
 
105
    /* Average of L1 and L3 */
 
106
    avg_l = (l1_l + l3_l) / 2;
 
107
    avg_c = (l1_c + l3_c) / 2;
 
108
 
 
109
    if (Pos == 0) {
 
110
      avg_l__1 = avg_l;
 
111
      avg_c__1 = avg_c;
 
112
    }
 
113
 
 
114
    /* Average of next L1 and next L3 */
 
115
    avg_l_1 = (l1_1_l + l3_1_l) / 2;
 
116
    avg_c_1 = (l1_1_c + l3_1_c) / 2;
 
117
 
 
118
    /* Calculate average of one pixel forward and previous */
 
119
    avg_s_l = (avg_l__1 + avg_l_1) / 2;
 
120
    avg_s_c = (avg_c__1 + avg_c_1) / 2;
 
121
 
 
122
    /* Calculate average of center and surrounding pixels */
 
123
    avg_sc_l = (avg_l + avg_s_l) / 2;
 
124
    avg_sc_c = (avg_c + avg_s_c) / 2;
 
125
 
 
126
    /* move forward */
 
127
    avg_l__1 = avg_l;
 
128
    avg_c__1 = avg_c;
 
129
 
 
130
    /* Get best L2/L2P, i.e. least diff from above average */
 
131
    l2_l = L2[0];
 
132
    l2_c = L2[1];
 
133
    lp2_l = L2P[0];
 
134
    lp2_c = L2P[1];
 
135
 
 
136
    l2_l_diff = ABS (l2_l - avg_sc_l);
 
137
    l2_c_diff = ABS (l2_c - avg_sc_c);
 
138
 
 
139
    lp2_l_diff = ABS (lp2_l - avg_sc_l);
 
140
    lp2_c_diff = ABS (lp2_c - avg_sc_c);
 
141
 
 
142
    if (l2_l_diff > lp2_l_diff)
 
143
      best_l = lp2_l;
 
144
    else
 
145
      best_l = l2_l;
 
146
 
 
147
    if (l2_c_diff > lp2_c_diff)
 
148
      best_c = lp2_c;
 
149
    else
 
150
      best_c = l2_c;
 
151
 
 
152
    /* Clip this best L2/L2P by L1/L3 and allow to differ by GreedyMaxComb */
 
153
    max_l = MAX (l1_l, l3_l);
 
154
    min_l = MIN (l1_l, l3_l);
 
155
 
 
156
    if (max_l < 256 - max_comb)
 
157
      max_l += max_comb;
 
158
    else
 
159
      max_l = 255;
 
160
 
 
161
    if (min_l > max_comb)
 
162
      min_l -= max_comb;
 
163
    else
 
164
      min_l = 0;
 
165
 
 
166
    max_c = MAX (l1_c, l3_c);
 
167
    min_c = MIN (l1_c, l3_c);
 
168
 
 
169
    if (max_c < 256 - max_comb)
 
170
      max_c += max_comb;
 
171
    else
 
172
      max_c = 255;
 
173
 
 
174
    if (min_c > max_comb)
 
175
      min_c -= max_comb;
 
176
    else
 
177
      min_c = 0;
 
178
 
 
179
    out_l = CLAMP (best_l, min_l, max_l);
 
180
    out_c = CLAMP (best_c, min_c, max_c);
 
181
 
 
182
    /* Do motion compensation for luma, i.e. how much
 
183
     * the weave pixel differs */
 
184
    mov_l = ABS (l2_l - lp2_l);
 
185
    if (mov_l > motion_threshold)
 
186
      mov_l -= motion_threshold;
 
187
    else
 
188
      mov_l = 0;
 
189
 
 
190
    mov_l = mov_l * motion_sense;
 
191
    if (mov_l > 256)
 
192
      mov_l = 256;
 
193
 
 
194
    /* Weighted sum on clipped weave pixel and average */
 
195
    out_l = (out_l * (256 - mov_l) + avg_sc_l * mov_l) / 256;
 
196
 
 
197
    Dest[0] = out_l;
 
198
    Dest[1] = out_c;
 
199
 
 
200
    Dest += 2;
 
201
    L1 += 2;
 
202
    L2 += 2;
 
203
    L3 += 2;
 
204
    L2P += 2;
 
205
  }
 
206
}
 
207
 
 
208
#ifdef BUILD_X86_ASM
 
209
 
 
210
#define IS_MMXEXT
 
211
#define SIMD_TYPE MMXEXT
 
212
#define FUNCT_NAME greedyDScaler_MMXEXT
 
213
#include "greedyh.asm"
 
214
#undef SIMD_TYPE
 
215
#undef IS_MMXEXT
 
216
#undef FUNCT_NAME
 
217
 
 
218
#define IS_3DNOW
 
219
#define SIMD_TYPE 3DNOW
 
220
#define FUNCT_NAME greedyDScaler_3DNOW
 
221
#include "greedyh.asm"
 
222
#undef SIMD_TYPE
 
223
#undef IS_3DNOW
 
224
#undef FUNCT_NAME
 
225
 
 
226
#define IS_MMX
 
227
#define SIMD_TYPE MMX
 
228
#define FUNCT_NAME greedyDScaler_MMX
 
229
#include "greedyh.asm"
 
230
#undef SIMD_TYPE
 
231
#undef IS_MMX
 
232
#undef FUNCT_NAME
 
233
 
 
234
#endif
 
235
 
 
236
static void
 
237
deinterlace_frame_di_greedyh (GstDeinterlaceMethod * d_method,
 
238
    GstDeinterlace2 * object)
 
239
{
 
240
  GstDeinterlaceMethodGreedyH *self =
 
241
      GST_DEINTERLACE_METHOD_GREEDY_H (d_method);
 
242
  GstDeinterlaceMethodGreedyHClass *klass =
 
243
      GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
 
244
  int InfoIsOdd = 0;
 
245
  int Line;
 
246
  unsigned int Pitch = object->field_stride;
 
247
 
 
248
  unsigned char *L1;            // ptr to Line1, of 3
 
249
  unsigned char *L2;            // ptr to Line2, the weave line
 
250
  unsigned char *L3;            // ptr to Line3
 
251
 
 
252
  unsigned char *L2P;           // ptr to prev Line2
 
253
  unsigned char *Dest = GST_BUFFER_DATA (object->out_buf);
 
254
 
 
255
  // copy first even line no matter what, and the first odd line if we're
 
256
  // processing an EVEN field. (note diff from other deint rtns.)
 
257
 
 
258
  if (object->field_history[object->history_count - 1].flags ==
 
259
      PICTURE_INTERLACED_BOTTOM) {
 
260
    InfoIsOdd = 1;
 
261
 
 
262
    L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
 
263
    L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf);
 
264
    L3 = L1 + Pitch;
 
265
    L2P =
 
266
        GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf);
 
267
 
 
268
    // copy first even line
 
269
    oil_memcpy (Dest, L1, object->line_length);
 
270
    Dest += object->output_stride;
 
271
  } else {
 
272
    InfoIsOdd = 0;
 
273
    L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
 
274
    L2 = GST_BUFFER_DATA (object->field_history[object->history_count -
 
275
            1].buf) + Pitch;
 
276
    L3 = L1 + Pitch;
 
277
    L2P =
 
278
        GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) +
 
279
        Pitch;
 
280
 
 
281
    // copy first even line
 
282
    oil_memcpy (Dest, GST_BUFFER_DATA (object->field_history[0].buf),
 
283
        object->line_length);
 
284
    Dest += object->output_stride;
 
285
    // then first odd line
 
286
    oil_memcpy (Dest, L1, object->line_length);
 
287
    Dest += object->output_stride;
 
288
  }
 
289
 
 
290
  for (Line = 0; Line < (object->field_height - 1); ++Line) {
 
291
    klass->scanline (self, L1, L2, L3, L2P, Dest, object->line_length);
 
292
    Dest += object->output_stride;
 
293
    oil_memcpy (Dest, L3, object->line_length);
 
294
    Dest += object->output_stride;
 
295
 
 
296
    L1 += Pitch;
 
297
    L2 += Pitch;
 
298
    L3 += Pitch;
 
299
    L2P += Pitch;
 
300
  }
 
301
 
 
302
  if (InfoIsOdd) {
 
303
    oil_memcpy (Dest, L2, object->line_length);
 
304
  }
 
305
}
 
306
 
 
307
G_DEFINE_TYPE (GstDeinterlaceMethodGreedyH, gst_deinterlace_method_greedy_h,
 
308
    GST_TYPE_DEINTERLACE_METHOD);
 
309
 
 
310
enum
 
311
{
 
312
  ARG_0,
 
313
  ARG_MAX_COMB,
 
314
  ARG_MOTION_THRESHOLD,
 
315
  ARG_MOTION_SENSE
 
316
};
 
317
 
 
318
static void
 
319
gst_deinterlace_method_greedy_h_set_property (GObject * object, guint prop_id,
 
320
    const GValue * value, GParamSpec * pspec)
 
321
{
 
322
  GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
 
323
 
 
324
  switch (prop_id) {
 
325
    case ARG_MAX_COMB:
 
326
      self->max_comb = g_value_get_uint (value);
 
327
      break;
 
328
    case ARG_MOTION_THRESHOLD:
 
329
      self->motion_threshold = g_value_get_uint (value);
 
330
      break;
 
331
    case ARG_MOTION_SENSE:
 
332
      self->motion_sense = g_value_get_uint (value);
 
333
      break;
 
334
    default:
 
335
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
336
  }
 
337
}
 
338
 
 
339
static void
 
340
gst_deinterlace_method_greedy_h_get_property (GObject * object, guint prop_id,
 
341
    GValue * value, GParamSpec * pspec)
 
342
{
 
343
  GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
 
344
 
 
345
  switch (prop_id) {
 
346
    case ARG_MAX_COMB:
 
347
      g_value_set_uint (value, self->max_comb);
 
348
      break;
 
349
    case ARG_MOTION_THRESHOLD:
 
350
      g_value_set_uint (value, self->motion_threshold);
 
351
      break;
 
352
    case ARG_MOTION_SENSE:
 
353
      g_value_set_uint (value, self->motion_sense);
 
354
      break;
 
355
    default:
 
356
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
357
  }
 
358
}
 
359
 
 
360
static void
 
361
gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass *
 
362
    klass)
 
363
{
 
364
  GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
 
365
  GObjectClass *gobject_class = (GObjectClass *) klass;
 
366
#ifdef BUILD_X86_ASM
 
367
  guint cpu_flags = oil_cpu_get_flags ();
 
368
#endif
 
369
 
 
370
  gobject_class->set_property = gst_deinterlace_method_greedy_h_set_property;
 
371
  gobject_class->get_property = gst_deinterlace_method_greedy_h_get_property;
 
372
 
 
373
  g_object_class_install_property (gobject_class, ARG_MAX_COMB,
 
374
      g_param_spec_uint ("max-comb",
 
375
          "Max comb",
 
376
          "Max Comb", 0, 255, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
 
377
      );
 
378
 
 
379
  g_object_class_install_property (gobject_class, ARG_MOTION_THRESHOLD,
 
380
      g_param_spec_uint ("motion-threshold",
 
381
          "Motion Threshold",
 
382
          "Motion Threshold",
 
383
          0, 255, 25, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
 
384
      );
 
385
 
 
386
  g_object_class_install_property (gobject_class, ARG_MOTION_SENSE,
 
387
      g_param_spec_uint ("motion-sense",
 
388
          "Motion Sense",
 
389
          "Motion Sense",
 
390
          0, 255, 30, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
 
391
      );
 
392
 
 
393
  dim_class->fields_required = 4;
 
394
  dim_class->deinterlace_frame = deinterlace_frame_di_greedyh;
 
395
  dim_class->name = "Motion Adaptive: Advanced Detection";
 
396
  dim_class->nick = "greedyh";
 
397
  dim_class->latency = 1;
 
398
 
 
399
#ifdef BUILD_X86_ASM
 
400
  if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
 
401
    klass->scanline = greedyDScaler_MMXEXT;
 
402
  } else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) {
 
403
    klass->scanline = greedyDScaler_3DNOW;
 
404
  } else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
 
405
    klass->scanline = greedyDScaler_MMX;
 
406
  } else {
 
407
    klass->scanline = greedyDScaler_C;
 
408
  }
 
409
#else
 
410
  klass->scanline = greedyDScaler_C;
 
411
#endif
 
412
}
 
413
 
 
414
static void
 
415
gst_deinterlace_method_greedy_h_init (GstDeinterlaceMethodGreedyH * self)
 
416
{
 
417
  self->max_comb = 5;
 
418
  self->motion_threshold = 25;
 
419
  self->motion_sense = 30;
 
420
}