~ubuntu-branches/ubuntu/intrepid/gstreamer0.10-ffmpeg/intrepid

« back to all changes in this revision

Viewing changes to ext/libpostproc/gstpostproc.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2006-12-13 23:10:28 UTC
  • mto: This revision was merged to the branch mainline in revision 10.
  • Revision ID: james.westby@ubuntu.com-20061213231028-9vl0epppqnwbq78i
Tags: upstream-0.10.2
Import upstream version 0.10.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright (C) 2005 Edward Hervey (edward@fluendo.com)
 
3
    Copyright (C) 2006 Mark Nauwelaerts (manauw@skynet.be)
 
4
 
 
5
    This program is free software; you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License as published by
 
7
    the Free Software Foundation; either version 2 of the License, or
 
8
    (at your option) any later version.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program; if not, write to the Free Software
 
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
*/
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include <gst/gst.h>
 
25
#include <gst/video/video.h>
 
26
#include <gst/video/gstvideofilter.h>
 
27
#include <liboil/liboil.h>
 
28
#include <liboil/liboilcpu.h>
 
29
#include <liboil/liboilfunction.h>
 
30
 
 
31
#ifdef HAVE_FFMPEG_UNINSTALLED
 
32
#include <avcodec.h>
 
33
#include <version.h>
 
34
#include <libpostproc/postprocess.h>
 
35
#else
 
36
#include <ffmpeg/avcodec.h>
 
37
#include <ffmpeg/version.h>
 
38
#include <ffmpeg/libpostproc/postprocess.h>
 
39
#endif
 
40
 
 
41
 
 
42
typedef struct _PostProcDetails PostProcDetails;
 
43
 
 
44
struct _PostProcDetails {
 
45
  char  *shortname;
 
46
  char  *longname;
 
47
  char  *description;
 
48
};
 
49
 
 
50
static PostProcDetails filterdetails[] = {
 
51
  {"hb", "hdeblock",            "horizontal deblocking filter"},
 
52
  {"vb", "vdeblock",            "vertical deblocking filter"},
 
53
  {"h1", "x1hdeblock",          "experimental horizontal deblocking filter 1"},
 
54
  {"v1", "x1vdeblock",          "experimental vertical deblocking filter 1"},
 
55
  {"ha", "ahdeblock",           "another horizontal deblocking filter"},
 
56
  {"va", "avdeblock",           "another vertical deblocking filter"},
 
57
  {"dr", "dering",              "deringing filter"},
 
58
  {"al", "autolevels",          "automatic brightness/contrast filter"},
 
59
  {"lb", "linblenddeint",       "linear blend interpolater"},
 
60
  {"li", "linipoldeint",        "linear interpolation deinterlacer"},
 
61
  {"ci", "cubicipoldeint",      "cubic interpolation deinterlacer"},
 
62
  {"md", "mediandeint",         "median deinterlacer"},
 
63
  {"fd", "ffmpegdeint",         "ffmpeg deinterlacer"},
 
64
  {"l5", "lowpass5",            "FIR lowpass deinterlacer"},
 
65
  {"tn", "tmpnoise",            "temporal noise reducer"},
 
66
  {"fq", "forcequant",          "force quantizer"},
 
67
  {"de", "default",             "default filters"},
 
68
  {NULL, NULL,                  NULL}
 
69
};
 
70
 
 
71
typedef struct  _GstPostProc GstPostProc;
 
72
 
 
73
struct  _GstPostProc
 
74
{
 
75
  GstVideoFilter element;
 
76
 
 
77
  GstPad *sinkpad, *srcpad;
 
78
  guint quality;
 
79
  gint width, height;
 
80
 
 
81
  gint ystride, ustride, vstride;
 
82
  gint ysize, usize, vsize;
 
83
 
 
84
  pp_mode_t *mode;
 
85
  pp_context_t *context;
 
86
 
 
87
  /* props of various filters */
 
88
  gboolean autoq;
 
89
  guint scope;
 
90
  /* though not all needed at once,
 
91
   * this avoids union or ugly re-use for simplicity */
 
92
  gint diff, flat;
 
93
  gint t1, t2, t3;
 
94
  gboolean range;
 
95
  gint quant;
 
96
 
 
97
  /* argument string for pp */
 
98
  gchar *cargs, *args;
 
99
};
 
100
 
 
101
typedef struct  _GstPostProcClass GstPostProcClass;
 
102
 
 
103
struct  _GstPostProcClass
 
104
{
 
105
  GstVideoFilterClass parent_class;
 
106
 
 
107
  gint filterid;
 
108
};
 
109
 
 
110
/* properties for the various pp filters */
 
111
/* common props */
 
112
enum
 
113
{
 
114
  PROP_0,
 
115
  PROP_QUALITY,
 
116
  PROP_AUTOQ,
 
117
  PROP_SCOPE,
 
118
  PROP_MAX
 
119
};
 
120
 
 
121
/* possible filter scopes */
 
122
enum
 
123
{
 
124
  SCOPE_BOTH,
 
125
  SCOPE_CHROMA,
 
126
  SCOPE_LUMA
 
127
};
 
128
 
 
129
#define DEFAULT_QUALITY   PP_QUALITY_MAX
 
130
#define DEFAULT_AUTOQ     FALSE
 
131
#define DEFAULT_SCOPE     SCOPE_BOTH
 
132
 
 
133
/* deblocking props */
 
134
enum
 
135
{
 
136
  PROP_DIFF = PROP_MAX,
 
137
  PROP_FLAT
 
138
};
 
139
 
 
140
#define DEFAULT_DIFF    -1
 
141
#define DEFAULT_FLAT    -1
 
142
 
 
143
/* denoise props */
 
144
enum
 
145
{
 
146
  PROP_T1 = PROP_MAX,
 
147
  PROP_T2,
 
148
  PROP_T3
 
149
};
 
150
 
 
151
#define DEFAULT_T1    -1
 
152
#define DEFAULT_T2    -1
 
153
#define DEFAULT_T3    -1
 
154
 
 
155
/* autolevels */
 
156
enum
 
157
{
 
158
  PROP_RANGE = PROP_MAX
 
159
};
 
160
 
 
161
#define DEFAULT_RANGE FALSE
 
162
 
 
163
/* forceq props */
 
164
enum
 
165
{
 
166
  PROP_QUANT = PROP_MAX
 
167
};
 
168
 
 
169
#define DEFAULT_QUANT  -1
 
170
 
 
171
 
 
172
/* hashtable, key = gtype, value = filterdetails index */
 
173
static GHashTable *global_plugins;
 
174
 
 
175
/* TODO : add support for the other format supported by libpostproc */
 
176
 
 
177
static GstStaticPadTemplate gst_post_proc_src_template =
 
178
GST_STATIC_PAD_TEMPLATE ("src",
 
179
    GST_PAD_SRC,
 
180
    GST_PAD_ALWAYS,
 
181
    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
 
182
    );
 
183
 
 
184
static GstStaticPadTemplate gst_post_proc_sink_template =
 
185
GST_STATIC_PAD_TEMPLATE ("sink",
 
186
    GST_PAD_SINK,
 
187
    GST_PAD_ALWAYS,
 
188
    GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
 
189
    );
 
190
 
 
191
GST_DEBUG_CATEGORY (postproc_debug);
 
192
#define GST_CAT_DEFAULT postproc_debug
 
193
 
 
194
static void gst_post_proc_class_init (GstPostProcClass * klass);
 
195
static void gst_post_proc_base_init (GstPostProcClass * klass);
 
196
static void gst_post_proc_init (GstPostProc * pproc);
 
197
static void gst_post_proc_dispose (GObject * object);
 
198
 
 
199
static gboolean gst_post_proc_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
 
200
    GstCaps * outcaps);
 
201
static GstFlowReturn gst_post_proc_transform_ip (GstBaseTransform * btrans,
 
202
    GstBuffer * in);
 
203
 
 
204
/* static GstStateChangeReturn gst_post_proc_change_state (GstElement * element, */
 
205
/*     GstStateChange transition); */
 
206
 
 
207
static void gst_post_proc_set_property (GObject * object,
 
208
    guint prop_id, const GValue * value, GParamSpec *pspec);
 
209
static void gst_post_proc_get_property (GObject * object,
 
210
    guint prop_id, GValue * value, GParamSpec *pspec);
 
211
static void gst_post_proc_deblock_set_property (GObject * object,
 
212
    guint prop_id, const GValue * value, GParamSpec *pspec);
 
213
static void gst_post_proc_deblock_get_property (GObject * object,
 
214
    guint prop_id, GValue * value, GParamSpec *pspec);
 
215
static void gst_post_proc_autolevels_set_property (GObject * object,
 
216
    guint prop_id, const GValue * value, GParamSpec *pspec);
 
217
static void gst_post_proc_autolevels_get_property (GObject * object,
 
218
    guint prop_id, GValue * value, GParamSpec *pspec);
 
219
static void gst_post_proc_tmpnoise_set_property (GObject * object,
 
220
    guint prop_id, const GValue * value, GParamSpec *pspec);
 
221
static void gst_post_proc_tmpnoise_get_property (GObject * object,
 
222
    guint prop_id, GValue * value, GParamSpec *pspec);
 
223
static void gst_post_proc_forcequant_set_property (GObject * object,
 
224
    guint prop_id, const GValue * value, GParamSpec *pspec);
 
225
static void gst_post_proc_forcequant_get_property (GObject * object,
 
226
    guint prop_id, GValue * value, GParamSpec *pspec);
 
227
 
 
228
static GstElementClass *parent_class = NULL;
 
229
 
 
230
#define GST_TYPE_PP_SCOPE (gst_pp_scope_get_type())
 
231
static GType
 
232
gst_pp_scope_get_type (void)
 
233
{
 
234
  static GType pp_scope_type = 0;
 
235
 
 
236
  static const GEnumValue pp_scope[] = {
 
237
    {0, "Chrominance and Luminance filtering", "both"},
 
238
    {1, "Chrominance only filtering", "chroma"},
 
239
    {2, "Luminance only filtering", "luma"},
 
240
    {0, NULL, NULL},
 
241
  };
 
242
 
 
243
  if (!pp_scope_type) {
 
244
    pp_scope_type =
 
245
        g_enum_register_static ("GstPostProcPPScope", pp_scope);
 
246
  }
 
247
  return pp_scope_type;
 
248
}
 
249
 
 
250
#ifndef GST_DISABLE_GST_DEBUG
 
251
static void
 
252
gst_ffmpeg_log_callback (void * ptr, int level, const char * fmt, va_list vl)
 
253
{
 
254
  GstDebugLevel gst_level;
 
255
 
 
256
  switch (level) {
 
257
    case AV_LOG_QUIET:
 
258
      gst_level = GST_LEVEL_NONE;
 
259
      break;
 
260
    case AV_LOG_ERROR:
 
261
      gst_level = GST_LEVEL_ERROR;
 
262
      break;
 
263
    case AV_LOG_INFO:
 
264
      gst_level = GST_LEVEL_INFO;
 
265
      break;
 
266
    case AV_LOG_DEBUG:
 
267
      gst_level = GST_LEVEL_DEBUG;
 
268
      break;
 
269
    default:
 
270
      gst_level = GST_LEVEL_INFO;
 
271
      break;
 
272
  }
 
273
 
 
274
  gst_debug_log_valist (postproc_debug, gst_level, "", "", 0, NULL, fmt, vl);
 
275
}
 
276
#endif
 
277
 
 
278
#define ROUND_UP_2(x)  (((x)+1)&~1)
 
279
#define ROUND_UP_4(x)  (((x)+3)&~3)
 
280
#define ROUND_UP_8(x)  (((x)+7)&~7)
 
281
 
 
282
static void
 
283
change_context (GstPostProc * postproc, gint width, gint height)
 
284
{
 
285
  guint flags;
 
286
  gint ppflags;
 
287
 
 
288
  GST_DEBUG_OBJECT (postproc, "change_context, width:%d, height:%d",
 
289
      width, height);
 
290
 
 
291
  if ((width != postproc->width) && (height != postproc->height)) {
 
292
    if (postproc->context)
 
293
      pp_free_context (postproc->context);
 
294
    flags = oil_cpu_get_flags();
 
295
    ppflags = (flags & OIL_IMPL_FLAG_MMX ? PP_CPU_CAPS_MMX : 0)
 
296
        | (flags & OIL_IMPL_FLAG_MMXEXT ? PP_CPU_CAPS_MMX2 : 0)
 
297
        | (flags & OIL_IMPL_FLAG_3DNOW ? PP_CPU_CAPS_3DNOW : 0)
 
298
        | (flags & OIL_IMPL_FLAG_ALTIVEC ? PP_CPU_CAPS_ALTIVEC : 0);
 
299
    postproc->context = pp_get_context (width, height, PP_FORMAT_420 | ppflags);
 
300
    postproc->width = width;
 
301
    postproc->height = height;
 
302
    postproc->ystride = ROUND_UP_4 (width);
 
303
    postproc->ustride = ROUND_UP_8 (width) / 2;
 
304
    postproc->vstride = ROUND_UP_8 (postproc->ystride) / 2;
 
305
    postproc->ysize = postproc->ystride * ROUND_UP_2 (height);
 
306
    postproc->usize = postproc->ustride * ROUND_UP_2 (height) / 2;
 
307
    postproc->vsize = postproc->vstride * ROUND_UP_2 (height) / 2;
 
308
    GST_DEBUG_OBJECT (postproc, "new strides are (YUV) : %d %d %d",
 
309
        postproc->ystride, postproc->ustride, postproc->vstride);
 
310
  }
 
311
}
 
312
 
 
313
/* append app to *base, and places result in *base */
 
314
/* all input strings are free'd */
 
315
static void inline
 
316
append (gchar ** base, gchar * app)
 
317
{
 
318
  gchar *res;
 
319
  gchar *sep;
 
320
 
 
321
  if (**base && *app)
 
322
    sep = ":";
 
323
  else
 
324
    sep = "";
 
325
  res = g_strconcat (*base, sep, app, NULL);
 
326
  g_free (*base);
 
327
  g_free (app);
 
328
  *base = res;
 
329
}
 
330
 
 
331
static void
 
332
change_mode (GstPostProc * postproc )
 
333
{
 
334
  GstPostProcClass * klass;
 
335
  gchar *name;
 
336
 
 
337
  klass = (GstPostProcClass *) G_OBJECT_GET_CLASS (G_OBJECT (postproc));
 
338
 
 
339
  if (postproc->mode)
 
340
    pp_free_mode (postproc->mode);
 
341
 
 
342
  name = g_strdup (filterdetails[klass->filterid].shortname);
 
343
  append (&name, g_strdup (postproc->cargs));
 
344
  append (&name, g_strdup (postproc->args));
 
345
  GST_DEBUG_OBJECT (postproc, "requesting pp %s", name);
 
346
  postproc->mode = pp_get_mode_by_name_and_quality (name, postproc->quality);
 
347
  g_free (name);
 
348
 
 
349
  g_assert (postproc->mode);
 
350
}
 
351
 
 
352
static void
 
353
gst_post_proc_base_init (GstPostProcClass * klass)
 
354
{
 
355
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
356
  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 
357
  GstElementDetails details;
 
358
  gint ppidx;
 
359
 
 
360
  ppidx = GPOINTER_TO_INT (g_hash_table_lookup (global_plugins,
 
361
      GINT_TO_POINTER (G_OBJECT_CLASS_TYPE (gobject_class))));
 
362
 
 
363
  details.longname = g_strdup_printf ("LibPostProc %s filter",
 
364
      filterdetails[ppidx].longname);
 
365
  details.klass = "Filter/Video";
 
366
  details.description = g_strdup_printf ("LibPostProc %s",
 
367
      filterdetails[ppidx].description);
 
368
  details.author = "Edward Hervey <edward@fluendo.com>, Mark Nauwelaerts (manauw@skynet.be)";
 
369
  gst_element_class_set_details (element_class, &details);
 
370
  g_free(details.longname);
 
371
  g_free(details.description);
 
372
 
 
373
  gst_element_class_add_pad_template (element_class, 
 
374
      gst_static_pad_template_get (&gst_post_proc_src_template));
 
375
  gst_element_class_add_pad_template (element_class,
 
376
      gst_static_pad_template_get (&gst_post_proc_sink_template));
 
377
 
 
378
  klass->filterid = ppidx;
 
379
}
 
380
 
 
381
static void
 
382
gst_post_proc_class_init (GstPostProcClass * klass)
 
383
{
 
384
  GObjectClass  *gobject_class = G_OBJECT_CLASS (klass);
 
385
/*   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); */
 
386
  GstBaseTransformClass *btrans_class = GST_BASE_TRANSFORM_CLASS (klass);
 
387
  gint ppidx;
 
388
 
 
389
  parent_class = g_type_class_peek_parent (klass);
 
390
 
 
391
  gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_post_proc_set_property);
 
392
  gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_post_proc_get_property);
 
393
 
 
394
  /* common props */
 
395
  g_object_class_install_property (gobject_class, PROP_QUALITY,
 
396
      g_param_spec_uint ("quality", "Quality",
 
397
          "Quality level of filter (higher is better)",
 
398
          0, PP_QUALITY_MAX, DEFAULT_QUALITY, G_PARAM_READWRITE));
 
399
 
 
400
  g_object_class_install_property (gobject_class, PROP_AUTOQ,
 
401
      g_param_spec_boolean ("autoq", "AutoQ",
 
402
          "Automatically switch filter off if CPU too slow",
 
403
          DEFAULT_AUTOQ, G_PARAM_READWRITE));
 
404
 
 
405
  g_object_class_install_property (gobject_class, PROP_SCOPE,
 
406
      g_param_spec_enum ("scope", "Scope",
 
407
          "Operate on chrominance and/or luminance",
 
408
          GST_TYPE_PP_SCOPE, DEFAULT_SCOPE, G_PARAM_READWRITE));
 
409
 
 
410
  ppidx = klass->filterid;
 
411
  /* per filter props */
 
412
  if (g_strrstr (filterdetails[ppidx].longname, "deblock") != NULL &&
 
413
      filterdetails[ppidx].longname[0] != 'x') {
 
414
    /* deblocking */
 
415
    g_object_class_install_property (gobject_class, PROP_DIFF,
 
416
        g_param_spec_int ("difference", "Difference Factor",
 
417
            "Higher values mean more deblocking (-1 = pp default)",
 
418
            -1, G_MAXINT, DEFAULT_DIFF, G_PARAM_READWRITE));
 
419
 
 
420
    g_object_class_install_property (gobject_class, PROP_FLAT,
 
421
        g_param_spec_int ("flatness", "Flatness Threshold",
 
422
            "Lower values mean more deblocking (-1 = pp default)",
 
423
            -1, G_MAXINT, DEFAULT_FLAT, G_PARAM_READWRITE));
 
424
 
 
425
    gobject_class->set_property =
 
426
        GST_DEBUG_FUNCPTR (gst_post_proc_deblock_set_property);
 
427
    gobject_class->get_property =
 
428
        GST_DEBUG_FUNCPTR (gst_post_proc_deblock_get_property);
 
429
  } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "tn"))) {
 
430
    /* tmpnoise */
 
431
    g_object_class_install_property (gobject_class, PROP_T1,
 
432
        g_param_spec_int ("threshold-1", "Threshold One",
 
433
            "Higher values mean stronger filtering (-1 = pp default)",
 
434
            -1, G_MAXINT, DEFAULT_T1, G_PARAM_READWRITE));
 
435
 
 
436
    g_object_class_install_property (gobject_class, PROP_T2,
 
437
        g_param_spec_int ("threshold-2", "Threshold Two",
 
438
            "Higher values mean stronger filtering (-1 = pp default)",
 
439
            -1, G_MAXINT, DEFAULT_T2, G_PARAM_READWRITE));
 
440
 
 
441
    g_object_class_install_property (gobject_class, PROP_T3,
 
442
        g_param_spec_int ("threshold-3", "Threshold Three",
 
443
            "Higher values mean stronger filtering (-1 = pp default)",
 
444
            -1, G_MAXINT, DEFAULT_T3, G_PARAM_READWRITE));
 
445
 
 
446
    gobject_class->set_property =
 
447
        GST_DEBUG_FUNCPTR (gst_post_proc_tmpnoise_set_property);
 
448
    gobject_class->get_property =
 
449
        GST_DEBUG_FUNCPTR (gst_post_proc_tmpnoise_get_property);
 
450
  } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "al"))) {
 
451
    /* autolevels */
 
452
    g_object_class_install_property (gobject_class, PROP_RANGE,
 
453
        g_param_spec_boolean ("fully-range", "Fully Range",
 
454
            "Stretch luminance to (0-255)",
 
455
            DEFAULT_RANGE, G_PARAM_READWRITE));
 
456
 
 
457
    gobject_class->set_property =
 
458
        GST_DEBUG_FUNCPTR (gst_post_proc_autolevels_set_property);
 
459
    gobject_class->get_property =
 
460
        GST_DEBUG_FUNCPTR (gst_post_proc_autolevels_get_property);
 
461
 
 
462
  } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "fq"))) {
 
463
    /* forcequant */
 
464
    g_object_class_install_property (gobject_class, PROP_QUANT,
 
465
        g_param_spec_int ("quantizer", "Force Quantizer",
 
466
          "Quantizer to use (-1 = pp default)",
 
467
            -1, G_MAXINT, DEFAULT_QUANT, G_PARAM_READWRITE));
 
468
 
 
469
    gobject_class->set_property =
 
470
        GST_DEBUG_FUNCPTR (gst_post_proc_forcequant_set_property);
 
471
    gobject_class->get_property =
 
472
        GST_DEBUG_FUNCPTR (gst_post_proc_forcequant_get_property);
 
473
  }
 
474
 
 
475
  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_post_proc_dispose);
 
476
  btrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_post_proc_setcaps);
 
477
  btrans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_post_proc_transform_ip);
 
478
}
 
479
 
 
480
static void
 
481
gst_post_proc_init (GstPostProc * postproc)
 
482
{
 
483
  /* properties */
 
484
  postproc->quality = DEFAULT_QUALITY;
 
485
  postproc->autoq = DEFAULT_AUTOQ;
 
486
  postproc->scope = DEFAULT_SCOPE;
 
487
  postproc->diff = DEFAULT_DIFF;
 
488
  postproc->flat = DEFAULT_FLAT;
 
489
  postproc->quant = DEFAULT_QUANT;
 
490
  postproc->t1 = DEFAULT_T1;
 
491
  postproc->t2 = DEFAULT_T2;
 
492
  postproc->t3 = DEFAULT_T3;
 
493
  postproc->range = DEFAULT_RANGE;
 
494
  postproc->mode = NULL;
 
495
  postproc->cargs = g_strdup ("");
 
496
  postproc->args = g_strdup ("");
 
497
  change_mode (postproc);
 
498
 
 
499
  postproc->context = NULL;
 
500
  postproc->width = 0;
 
501
  postproc->height = 0;
 
502
  postproc->ystride = 0;
 
503
  postproc->ustride = 0;
 
504
  postproc->vstride = 0;
 
505
  postproc->ysize = 0;
 
506
  postproc->usize = 0;
 
507
  postproc->vsize = 0;
 
508
}
 
509
 
 
510
static void
 
511
gst_post_proc_dispose (GObject * object)
 
512
{
 
513
  GstPostProc * postproc = (GstPostProc *) object;
 
514
 
 
515
  if (postproc->mode)
 
516
    pp_free_mode (postproc->mode);
 
517
  if (postproc->context)
 
518
    pp_free_context (postproc->context);
 
519
 
 
520
  g_free (postproc->cargs);
 
521
  postproc->cargs = NULL;
 
522
  g_free (postproc->args);
 
523
  postproc->args = NULL;
 
524
 
 
525
  G_OBJECT_CLASS (parent_class)->dispose (object);
 
526
}
 
527
 
 
528
static gboolean
 
529
gst_post_proc_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
 
530
    GstCaps * outcaps)
 
531
{
 
532
  GstPostProc *postproc = (GstPostProc *) (btrans);
 
533
  GstStructure *structure;
 
534
  gboolean ret = FALSE;
 
535
  gint width, height;
 
536
 
 
537
  structure = gst_caps_get_structure (incaps, 0);
 
538
 
 
539
  if (gst_structure_get_int (structure, "width", &width) &&
 
540
      gst_structure_get_int (structure, "height", &height)) {
 
541
    change_context (postproc, width, height);
 
542
    ret = TRUE;
 
543
  }
 
544
 
 
545
  return ret;
 
546
}
 
547
 
 
548
static GstFlowReturn
 
549
gst_post_proc_transform_ip (GstBaseTransform * btrans, GstBuffer * in)
 
550
{
 
551
  GstPostProc *postproc;
 
552
  gint stride[3];
 
553
  guint8 *outplane[3];
 
554
 
 
555
  /* postprocess the buffer !*/
 
556
  postproc = (GstPostProc *) btrans;
 
557
 
 
558
  stride[0] = postproc->ystride;
 
559
  stride[1] = postproc->ustride;
 
560
  stride[2] = postproc->vstride;
 
561
  outplane[0] = GST_BUFFER_DATA (in);
 
562
  outplane[1] = outplane[0] + postproc->ysize;
 
563
  outplane[2] = outplane[1] + postproc->usize;
 
564
 
 
565
  GST_DEBUG_OBJECT (postproc, "calling pp_postprocess, width:%d, height:%d",
 
566
      postproc->width, postproc->height);
 
567
 
 
568
  pp_postprocess (outplane, stride, outplane, stride,
 
569
      postproc->width, postproc->height, (int8_t*) "", 0,
 
570
      postproc->mode, postproc->context, 0);
 
571
 
 
572
  return GST_FLOW_OK;
 
573
}
 
574
 
 
575
 
 
576
static void
 
577
gst_post_proc_set_property (GObject * object, guint prop_id,
 
578
    const GValue * value, GParamSpec *pspec)
 
579
{
 
580
  GstPostProc *postproc = (GstPostProc *) object;
 
581
  gint quality;
 
582
  gchar *args;
 
583
 
 
584
  switch (prop_id) {
 
585
    case PROP_QUALITY:
 
586
      quality = g_value_get_uint (value);
 
587
    break;
 
588
    case PROP_AUTOQ:
 
589
      postproc->autoq = g_value_get_boolean (value);
 
590
      break;
 
591
    case PROP_SCOPE:
 
592
      postproc->scope = g_value_get_enum (value);
 
593
      break;
 
594
  default:
 
595
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
596
    break;
 
597
  }
 
598
 
 
599
  /* construct common args */
 
600
  args = postproc->autoq ? g_strdup ("autoq") : g_strdup ("");
 
601
  switch (postproc->scope) {
 
602
    case SCOPE_BOTH:
 
603
      break;
 
604
    case SCOPE_CHROMA:
 
605
      append (&args, g_strdup ("noluma"));
 
606
      break;
 
607
    case SCOPE_LUMA:
 
608
      append (&args, g_strdup ("nochrom"));
 
609
      break;
 
610
    default:
 
611
      g_assert_not_reached ();
 
612
      break;
 
613
  }
 
614
 
 
615
  g_free (postproc->cargs);
 
616
  postproc->cargs = args;
 
617
 
 
618
  change_mode (postproc);
 
619
}
 
620
 
 
621
static void
 
622
gst_post_proc_get_property (GObject * object, guint prop_id,
 
623
    GValue * value, GParamSpec *pspec)
 
624
{
 
625
  GstPostProc *postproc = (GstPostProc *) object;
 
626
 
 
627
  switch (prop_id) {
 
628
    case PROP_QUALITY:
 
629
      g_value_set_uint (value, postproc->quality);
 
630
      break;
 
631
    case PROP_AUTOQ:
 
632
      g_value_set_boolean (value, postproc->autoq);
 
633
      break;
 
634
    case PROP_SCOPE:
 
635
      g_value_set_enum (value, postproc->scope);
 
636
      break;
 
637
    default:
 
638
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
639
    break;
 
640
  }
 
641
}
 
642
 
 
643
 
 
644
static void
 
645
gst_post_proc_deblock_set_property (GObject * object, guint prop_id,
 
646
    const GValue * value, GParamSpec *pspec)
 
647
{
 
648
  GstPostProc *postproc = (GstPostProc *) object;
 
649
 
 
650
  switch (prop_id) {
 
651
    case PROP_DIFF:
 
652
      postproc->diff = g_value_get_int (value);
 
653
      break;
 
654
    case PROP_FLAT:
 
655
      postproc->flat = g_value_get_int (value);
 
656
      break;
 
657
    default:
 
658
      gst_post_proc_set_property (object, prop_id, value, pspec);
 
659
      break;
 
660
  }
 
661
 
 
662
  /* construct args */
 
663
  g_free (postproc->args);
 
664
  if (postproc->diff >= 0) {
 
665
    postproc->args = g_strdup_printf ("%d", postproc->diff);
 
666
    if (postproc->flat >= 0)
 
667
      append (&postproc->args, g_strdup_printf ("%d", postproc->flat));
 
668
  } else
 
669
    postproc->args = g_strdup ("");
 
670
  change_mode (postproc);
 
671
}
 
672
 
 
673
static void
 
674
gst_post_proc_deblock_get_property ( GObject * object, guint prop_id,
 
675
    GValue * value, GParamSpec *pspec )
 
676
{
 
677
  GstPostProc *postproc = (GstPostProc *) object;
 
678
 
 
679
  switch (prop_id) {
 
680
    case PROP_DIFF:
 
681
      g_value_set_int (value, postproc->diff);
 
682
      break;
 
683
    case PROP_FLAT:
 
684
      g_value_set_int (value, postproc->flat);
 
685
      break;
 
686
    default:
 
687
      gst_post_proc_get_property (object, prop_id, value, pspec);
 
688
      break;
 
689
  }
 
690
}
 
691
 
 
692
static void
 
693
gst_post_proc_tmpnoise_set_property (GObject * object, guint prop_id,
 
694
    const GValue * value, GParamSpec *pspec)
 
695
{
 
696
  GstPostProc *postproc = (GstPostProc *) object;
 
697
 
 
698
  switch (prop_id) {
 
699
    case PROP_T1:
 
700
      postproc->t1 = g_value_get_int (value);
 
701
      break;
 
702
    case PROP_T2:
 
703
      postproc->t2 = g_value_get_int (value);
 
704
      break;
 
705
    case PROP_T3:
 
706
      postproc->t3 = g_value_get_int (value);
 
707
      break;
 
708
    default:
 
709
      gst_post_proc_set_property (object, prop_id, value, pspec);
 
710
      break;
 
711
  }
 
712
 
 
713
  /* construct args */
 
714
  g_free (postproc->args);
 
715
  if (postproc->t1 >= 0) {
 
716
    postproc->args = g_strdup_printf ("%d", postproc->t1);
 
717
    if (postproc->t2 >= 0) {
 
718
      append (&postproc->args, g_strdup_printf ("%d", postproc->t2));
 
719
      if (postproc->t3 >= 0)
 
720
        append (&postproc->args, g_strdup_printf ("%d", postproc->t3));
 
721
    }
 
722
  } else
 
723
    postproc->args = g_strdup ("");
 
724
  change_mode (postproc);
 
725
}
 
726
 
 
727
static void
 
728
gst_post_proc_tmpnoise_get_property (GObject * object, guint prop_id,
 
729
    GValue * value, GParamSpec *pspec )
 
730
{
 
731
  GstPostProc *postproc = (GstPostProc *) object;
 
732
 
 
733
  switch (prop_id) {
 
734
    case PROP_T1:
 
735
      g_value_set_int (value, postproc->t1);
 
736
      break;
 
737
    case PROP_T2:
 
738
      g_value_set_int (value, postproc->t2);
 
739
      break;
 
740
    case PROP_T3:
 
741
      g_value_set_int (value, postproc->t3);
 
742
      break;
 
743
    default:
 
744
      gst_post_proc_get_property (object, prop_id, value, pspec);
 
745
      break;
 
746
  }
 
747
}
 
748
 
 
749
static void
 
750
gst_post_proc_autolevels_set_property (GObject * object, guint prop_id,
 
751
    const GValue * value, GParamSpec *pspec)
 
752
{
 
753
  GstPostProc *postproc = (GstPostProc *) object;
 
754
 
 
755
  switch (prop_id) {
 
756
    case PROP_RANGE:
 
757
      postproc->range = g_value_get_boolean (value);
 
758
      break;
 
759
    default:
 
760
      gst_post_proc_set_property (object, prop_id, value, pspec);
 
761
      break;
 
762
  }
 
763
 
 
764
  /* construct args */
 
765
  g_free (postproc->args);
 
766
  if (postproc->range)
 
767
    postproc->args = g_strdup ("f");
 
768
  else
 
769
    postproc->args = g_strdup ("");
 
770
  change_mode (postproc);
 
771
}
 
772
 
 
773
static void
 
774
gst_post_proc_autolevels_get_property (GObject * object, guint prop_id,
 
775
    GValue * value, GParamSpec *pspec )
 
776
{
 
777
  GstPostProc *postproc = (GstPostProc *) object;
 
778
 
 
779
  switch (prop_id) {
 
780
    case PROP_RANGE:
 
781
      g_value_set_boolean (value, postproc->range);
 
782
      break;
 
783
    default:
 
784
      gst_post_proc_get_property (object, prop_id, value, pspec);
 
785
      break;
 
786
  }
 
787
}
 
788
 
 
789
static void
 
790
gst_post_proc_forcequant_set_property (GObject * object, guint prop_id,
 
791
    const GValue * value, GParamSpec *pspec)
 
792
{
 
793
  GstPostProc *postproc = (GstPostProc *) object;
 
794
 
 
795
  switch (prop_id) {
 
796
    case PROP_QUANT:
 
797
      postproc->quant = g_value_get_int (value);
 
798
      break;
 
799
    default:
 
800
      gst_post_proc_set_property (object, prop_id, value, pspec);
 
801
      break;
 
802
  }
 
803
 
 
804
  /* construct args */
 
805
  g_free (postproc->args);
 
806
  if (postproc->quant >= 0)
 
807
    postproc->args = g_strdup_printf ("%d", postproc->quant);
 
808
  else
 
809
    postproc->args = g_strdup ("");
 
810
  change_mode (postproc);
 
811
}
 
812
 
 
813
static void
 
814
gst_post_proc_forcequant_get_property (GObject * object, guint prop_id,
 
815
    GValue * value, GParamSpec *pspec )
 
816
{
 
817
  GstPostProc *postproc = (GstPostProc *) object;
 
818
 
 
819
  switch (prop_id) {
 
820
    case PROP_QUANT:
 
821
      g_value_set_int (value, postproc->quant);
 
822
      break;
 
823
    default:
 
824
      gst_post_proc_get_property (object, prop_id, value, pspec);
 
825
      break;
 
826
  }
 
827
}
 
828
 
 
829
 
 
830
gboolean
 
831
gst_post_proc_register(GstPlugin * plugin)
 
832
{
 
833
  GTypeInfo     typeinfo = {
 
834
    sizeof (GstPostProcClass),
 
835
    (GBaseInitFunc) gst_post_proc_base_init,
 
836
    NULL,
 
837
    (GClassInitFunc) gst_post_proc_class_init,
 
838
    NULL,
 
839
    NULL,
 
840
    sizeof (GstPostProc),
 
841
    0,
 
842
    (GInstanceInitFunc) gst_post_proc_init,
 
843
  };
 
844
  GType type;
 
845
  int i;
 
846
 
 
847
  global_plugins = g_hash_table_new (NULL, NULL);
 
848
  for (i = 0; filterdetails[i].shortname; i++) {
 
849
    gchar *type_name;
 
850
 
 
851
    g_hash_table_insert (global_plugins, GINT_TO_POINTER (0),
 
852
        GINT_TO_POINTER (i));
 
853
 
 
854
    /* create type_name */
 
855
    type_name = g_strdup_printf("postproc_%s", filterdetails[i].longname);
 
856
    if (g_type_from_name (type_name)) {
 
857
      g_free (type_name);
 
858
      continue;
 
859
    }
 
860
 
 
861
    /* create gtype */
 
862
    type = g_type_register_static (GST_TYPE_VIDEO_FILTER, type_name,
 
863
        &typeinfo, 0);
 
864
 
 
865
    g_hash_table_insert (global_plugins, GINT_TO_POINTER (type),
 
866
        GINT_TO_POINTER (i));
 
867
 
 
868
    /* register element */
 
869
    if (!gst_element_register (plugin, type_name, GST_RANK_PRIMARY, type)) {
 
870
      g_free(type_name);
 
871
      return FALSE;
 
872
    }
 
873
 
 
874
    g_free(type_name);
 
875
  }
 
876
  g_hash_table_remove (global_plugins, GINT_TO_POINTER (0));
 
877
 
 
878
  return TRUE;
 
879
}
 
880
 
 
881
static gboolean
 
882
plugin_init (GstPlugin * plugin)
 
883
{
 
884
  GST_DEBUG_CATEGORY_INIT (postproc_debug, "postproc", 0,
 
885
      "video postprocessing elements");
 
886
#ifndef GST_DISABLE_GST_DEBUG
 
887
  av_log_set_callback (gst_ffmpeg_log_callback);
 
888
#endif
 
889
 
 
890
  /* Register the filters */
 
891
  gst_post_proc_register (plugin);
 
892
 
 
893
  /* Now we can return the pointer to the newly created Plugin object. */
 
894
  return TRUE;
 
895
}
 
896
 
 
897
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
 
898
    GST_VERSION_MINOR,
 
899
    "postproc",
 
900
    "postprocessing elements",
 
901
    plugin_init,
 
902
    FFMPEG_VERSION, "GPL", "FFMpeg", "http://ffmpeg.sourceforge.net/")
 
903
 
 
904