2 Copyright (C) 2005 Edward Hervey (edward@fluendo.com)
3 Copyright (C) 2006 Mark Nauwelaerts (manauw@skynet.be)
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.
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.
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
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>
31 #ifdef HAVE_FFMPEG_UNINSTALLED
33 #include <postprocess.h>
35 #include <ffmpeg/avcodec.h>
36 #include <ffmpeg/libpostproc/postprocess.h>
40 typedef struct _PostProcDetails PostProcDetails;
42 struct _PostProcDetails {
48 static PostProcDetails filterdetails[] = {
49 {"hb", "hdeblock", "horizontal deblocking filter"},
50 {"vb", "vdeblock", "vertical deblocking filter"},
51 {"h1", "x1hdeblock", "experimental horizontal deblocking filter 1"},
52 {"v1", "x1vdeblock", "experimental vertical deblocking filter 1"},
53 {"ha", "ahdeblock", "another horizontal deblocking filter"},
54 {"va", "avdeblock", "another vertical deblocking filter"},
55 {"dr", "dering", "deringing filter"},
56 {"al", "autolevels", "automatic brightness/contrast filter"},
57 {"lb", "linblenddeint", "linear blend interpolater"},
58 {"li", "linipoldeint", "linear interpolation deinterlacer"},
59 {"ci", "cubicipoldeint", "cubic interpolation deinterlacer"},
60 {"md", "mediandeint", "median deinterlacer"},
61 {"fd", "ffmpegdeint", "ffmpeg deinterlacer"},
62 {"l5", "lowpass5", "FIR lowpass deinterlacer"},
63 {"tn", "tmpnoise", "temporal noise reducer"},
64 {"fq", "forcequant", "force quantizer"},
65 {"de", "default", "default filters"},
69 typedef struct _GstPostProc GstPostProc;
73 GstVideoFilter element;
75 GstPad *sinkpad, *srcpad;
79 gint ystride, ustride, vstride;
80 gint ysize, usize, vsize;
83 pp_context_t *context;
85 /* props of various filters */
88 /* though not all needed at once,
89 * this avoids union or ugly re-use for simplicity */
95 /* argument string for pp */
99 typedef struct _GstPostProcClass GstPostProcClass;
101 struct _GstPostProcClass
103 GstVideoFilterClass parent_class;
108 /* properties for the various pp filters */
119 /* possible filter scopes */
127 #define DEFAULT_QUALITY PP_QUALITY_MAX
128 #define DEFAULT_AUTOQ FALSE
129 #define DEFAULT_SCOPE SCOPE_BOTH
131 /* deblocking props */
134 PROP_DIFF = PROP_MAX,
138 #define DEFAULT_DIFF -1
139 #define DEFAULT_FLAT -1
149 #define DEFAULT_T1 -1
150 #define DEFAULT_T2 -1
151 #define DEFAULT_T3 -1
156 PROP_RANGE = PROP_MAX
159 #define DEFAULT_RANGE FALSE
164 PROP_QUANT = PROP_MAX
167 #define DEFAULT_QUANT -1
170 /* hashtable, key = gtype, value = filterdetails index */
171 static GHashTable *global_plugins;
173 /* TODO : add support for the other format supported by libpostproc */
175 static GstStaticPadTemplate gst_post_proc_src_template =
176 GST_STATIC_PAD_TEMPLATE ("src",
179 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
182 static GstStaticPadTemplate gst_post_proc_sink_template =
183 GST_STATIC_PAD_TEMPLATE ("sink",
186 GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
189 GST_DEBUG_CATEGORY (postproc_debug);
190 #define GST_CAT_DEFAULT postproc_debug
192 static void gst_post_proc_class_init (GstPostProcClass * klass);
193 static void gst_post_proc_base_init (GstPostProcClass * klass);
194 static void gst_post_proc_init (GstPostProc * pproc);
195 static void gst_post_proc_dispose (GObject * object);
197 static gboolean gst_post_proc_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
199 static GstFlowReturn gst_post_proc_transform_ip (GstBaseTransform * btrans,
202 /* static GstStateChangeReturn gst_post_proc_change_state (GstElement * element, */
203 /* GstStateChange transition); */
205 static void gst_post_proc_set_property (GObject * object,
206 guint prop_id, const GValue * value, GParamSpec *pspec);
207 static void gst_post_proc_get_property (GObject * object,
208 guint prop_id, GValue * value, GParamSpec *pspec);
209 static void gst_post_proc_deblock_set_property (GObject * object,
210 guint prop_id, const GValue * value, GParamSpec *pspec);
211 static void gst_post_proc_deblock_get_property (GObject * object,
212 guint prop_id, GValue * value, GParamSpec *pspec);
213 static void gst_post_proc_autolevels_set_property (GObject * object,
214 guint prop_id, const GValue * value, GParamSpec *pspec);
215 static void gst_post_proc_autolevels_get_property (GObject * object,
216 guint prop_id, GValue * value, GParamSpec *pspec);
217 static void gst_post_proc_tmpnoise_set_property (GObject * object,
218 guint prop_id, const GValue * value, GParamSpec *pspec);
219 static void gst_post_proc_tmpnoise_get_property (GObject * object,
220 guint prop_id, GValue * value, GParamSpec *pspec);
221 static void gst_post_proc_forcequant_set_property (GObject * object,
222 guint prop_id, const GValue * value, GParamSpec *pspec);
223 static void gst_post_proc_forcequant_get_property (GObject * object,
224 guint prop_id, GValue * value, GParamSpec *pspec);
226 static GstElementClass *parent_class = NULL;
228 #define GST_TYPE_PP_SCOPE (gst_pp_scope_get_type())
230 gst_pp_scope_get_type (void)
232 static GType pp_scope_type = 0;
234 static const GEnumValue pp_scope[] = {
235 {0, "Chrominance and Luminance filtering", "both"},
236 {1, "Chrominance only filtering", "chroma"},
237 {2, "Luminance only filtering", "luma"},
241 if (!pp_scope_type) {
243 g_enum_register_static ("GstPostProcPPScope", pp_scope);
245 return pp_scope_type;
248 #ifndef GST_DISABLE_GST_DEBUG
250 gst_ffmpeg_log_callback (void * ptr, int level, const char * fmt, va_list vl)
252 GstDebugLevel gst_level;
256 gst_level = GST_LEVEL_NONE;
259 gst_level = GST_LEVEL_ERROR;
262 gst_level = GST_LEVEL_INFO;
265 gst_level = GST_LEVEL_DEBUG;
268 gst_level = GST_LEVEL_INFO;
272 gst_debug_log_valist (postproc_debug, gst_level, "", "", 0, NULL, fmt, vl);
276 #define ROUND_UP_2(x) (((x)+1)&~1)
277 #define ROUND_UP_4(x) (((x)+3)&~3)
278 #define ROUND_UP_8(x) (((x)+7)&~7)
281 change_context (GstPostProc * postproc, gint width, gint height)
286 GST_DEBUG_OBJECT (postproc, "change_context, width:%d, height:%d",
289 if ((width != postproc->width) && (height != postproc->height)) {
290 if (postproc->context)
291 pp_free_context (postproc->context);
292 flags = oil_cpu_get_flags();
293 ppflags = (flags & OIL_IMPL_FLAG_MMX ? PP_CPU_CAPS_MMX : 0)
294 | (flags & OIL_IMPL_FLAG_MMXEXT ? PP_CPU_CAPS_MMX2 : 0)
295 | (flags & OIL_IMPL_FLAG_3DNOW ? PP_CPU_CAPS_3DNOW : 0)
296 | (flags & OIL_IMPL_FLAG_ALTIVEC ? PP_CPU_CAPS_ALTIVEC : 0);
297 postproc->context = pp_get_context (width, height, PP_FORMAT_420 | ppflags);
298 postproc->width = width;
299 postproc->height = height;
300 postproc->ystride = ROUND_UP_4 (width);
301 postproc->ustride = ROUND_UP_8 (width) / 2;
302 postproc->vstride = ROUND_UP_8 (postproc->ystride) / 2;
303 postproc->ysize = postproc->ystride * ROUND_UP_2 (height);
304 postproc->usize = postproc->ustride * ROUND_UP_2 (height) / 2;
305 postproc->vsize = postproc->vstride * ROUND_UP_2 (height) / 2;
306 GST_DEBUG_OBJECT (postproc, "new strides are (YUV) : %d %d %d",
307 postproc->ystride, postproc->ustride, postproc->vstride);
311 /* append app to *base, and places result in *base */
312 /* all input strings are free'd */
314 append (gchar ** base, gchar * app)
323 res = g_strconcat (*base, sep, app, NULL);
330 change_mode (GstPostProc * postproc )
332 GstPostProcClass * klass;
335 klass = (GstPostProcClass *) G_OBJECT_GET_CLASS (G_OBJECT (postproc));
338 pp_free_mode (postproc->mode);
340 name = g_strdup (filterdetails[klass->filterid].shortname);
341 append (&name, g_strdup (postproc->cargs));
342 append (&name, g_strdup (postproc->args));
343 GST_DEBUG_OBJECT (postproc, "requesting pp %s", name);
344 postproc->mode = pp_get_mode_by_name_and_quality (name, postproc->quality);
347 g_assert (postproc->mode);
351 gst_post_proc_base_init (GstPostProcClass * klass)
353 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
354 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
355 GstElementDetails details;
358 ppidx = GPOINTER_TO_INT (g_hash_table_lookup (global_plugins,
359 GINT_TO_POINTER (G_OBJECT_CLASS_TYPE (gobject_class))));
361 details.longname = g_strdup_printf ("LibPostProc %s filter",
362 filterdetails[ppidx].longname);
363 details.klass = "Filter/Video";
364 details.description = g_strdup_printf ("LibPostProc %s",
365 filterdetails[ppidx].description);
366 details.author = "Edward Hervey <edward@fluendo.com>, Mark Nauwelaerts (manauw@skynet.be)";
367 gst_element_class_set_details (element_class, &details);
368 g_free(details.longname);
369 g_free(details.description);
371 gst_element_class_add_pad_template (element_class,
372 gst_static_pad_template_get (&gst_post_proc_src_template));
373 gst_element_class_add_pad_template (element_class,
374 gst_static_pad_template_get (&gst_post_proc_sink_template));
376 klass->filterid = ppidx;
380 gst_post_proc_class_init (GstPostProcClass * klass)
382 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
383 /* GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); */
384 GstBaseTransformClass *btrans_class = GST_BASE_TRANSFORM_CLASS (klass);
387 parent_class = g_type_class_peek_parent (klass);
389 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_post_proc_set_property);
390 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_post_proc_get_property);
393 g_object_class_install_property (gobject_class, PROP_QUALITY,
394 g_param_spec_uint ("quality", "Quality",
395 "Quality level of filter (higher is better)",
396 0, PP_QUALITY_MAX, DEFAULT_QUALITY, G_PARAM_READWRITE));
398 g_object_class_install_property (gobject_class, PROP_AUTOQ,
399 g_param_spec_boolean ("autoq", "AutoQ",
400 "Automatically switch filter off if CPU too slow",
401 DEFAULT_AUTOQ, G_PARAM_READWRITE));
403 g_object_class_install_property (gobject_class, PROP_SCOPE,
404 g_param_spec_enum ("scope", "Scope",
405 "Operate on chrominance and/or luminance",
406 GST_TYPE_PP_SCOPE, DEFAULT_SCOPE, G_PARAM_READWRITE));
408 ppidx = klass->filterid;
409 /* per filter props */
410 if (g_strrstr (filterdetails[ppidx].longname, "deblock") != NULL &&
411 filterdetails[ppidx].longname[0] != 'x') {
413 g_object_class_install_property (gobject_class, PROP_DIFF,
414 g_param_spec_int ("difference", "Difference Factor",
415 "Higher values mean more deblocking (-1 = pp default)",
416 -1, G_MAXINT, DEFAULT_DIFF, G_PARAM_READWRITE));
418 g_object_class_install_property (gobject_class, PROP_FLAT,
419 g_param_spec_int ("flatness", "Flatness Threshold",
420 "Lower values mean more deblocking (-1 = pp default)",
421 -1, G_MAXINT, DEFAULT_FLAT, G_PARAM_READWRITE));
423 gobject_class->set_property =
424 GST_DEBUG_FUNCPTR (gst_post_proc_deblock_set_property);
425 gobject_class->get_property =
426 GST_DEBUG_FUNCPTR (gst_post_proc_deblock_get_property);
427 } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "tn"))) {
429 g_object_class_install_property (gobject_class, PROP_T1,
430 g_param_spec_int ("threshold-1", "Threshold One",
431 "Higher values mean stronger filtering (-1 = pp default)",
432 -1, G_MAXINT, DEFAULT_T1, G_PARAM_READWRITE));
434 g_object_class_install_property (gobject_class, PROP_T2,
435 g_param_spec_int ("threshold-2", "Threshold Two",
436 "Higher values mean stronger filtering (-1 = pp default)",
437 -1, G_MAXINT, DEFAULT_T2, G_PARAM_READWRITE));
439 g_object_class_install_property (gobject_class, PROP_T3,
440 g_param_spec_int ("threshold-3", "Threshold Three",
441 "Higher values mean stronger filtering (-1 = pp default)",
442 -1, G_MAXINT, DEFAULT_T3, G_PARAM_READWRITE));
444 gobject_class->set_property =
445 GST_DEBUG_FUNCPTR (gst_post_proc_tmpnoise_set_property);
446 gobject_class->get_property =
447 GST_DEBUG_FUNCPTR (gst_post_proc_tmpnoise_get_property);
448 } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "al"))) {
450 g_object_class_install_property (gobject_class, PROP_RANGE,
451 g_param_spec_boolean ("fully-range", "Fully Range",
452 "Stretch luminance to (0-255)",
453 DEFAULT_RANGE, G_PARAM_READWRITE));
455 gobject_class->set_property =
456 GST_DEBUG_FUNCPTR (gst_post_proc_autolevels_set_property);
457 gobject_class->get_property =
458 GST_DEBUG_FUNCPTR (gst_post_proc_autolevels_get_property);
460 } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "fq"))) {
462 g_object_class_install_property (gobject_class, PROP_QUANT,
463 g_param_spec_int ("quantizer", "Force Quantizer",
464 "Quantizer to use (-1 = pp default)",
465 -1, G_MAXINT, DEFAULT_QUANT, G_PARAM_READWRITE));
467 gobject_class->set_property =
468 GST_DEBUG_FUNCPTR (gst_post_proc_forcequant_set_property);
469 gobject_class->get_property =
470 GST_DEBUG_FUNCPTR (gst_post_proc_forcequant_get_property);
473 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_post_proc_dispose);
474 btrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_post_proc_setcaps);
475 btrans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_post_proc_transform_ip);
479 gst_post_proc_init (GstPostProc * postproc)
482 postproc->quality = DEFAULT_QUALITY;
483 postproc->autoq = DEFAULT_AUTOQ;
484 postproc->scope = DEFAULT_SCOPE;
485 postproc->diff = DEFAULT_DIFF;
486 postproc->flat = DEFAULT_FLAT;
487 postproc->quant = DEFAULT_QUANT;
488 postproc->t1 = DEFAULT_T1;
489 postproc->t2 = DEFAULT_T2;
490 postproc->t3 = DEFAULT_T3;
491 postproc->range = DEFAULT_RANGE;
492 postproc->mode = NULL;
493 postproc->cargs = g_strdup ("");
494 postproc->args = g_strdup ("");
495 change_mode (postproc);
497 postproc->context = NULL;
499 postproc->height = 0;
500 postproc->ystride = 0;
501 postproc->ustride = 0;
502 postproc->vstride = 0;
509 gst_post_proc_dispose (GObject * object)
511 GstPostProc * postproc = (GstPostProc *) object;
514 pp_free_mode (postproc->mode);
515 if (postproc->context)
516 pp_free_context (postproc->context);
518 g_free (postproc->cargs);
519 postproc->cargs = NULL;
520 g_free (postproc->args);
521 postproc->args = NULL;
523 G_OBJECT_CLASS (parent_class)->dispose (object);
527 gst_post_proc_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
530 GstPostProc *postproc = (GstPostProc *) (btrans);
531 GstStructure *structure;
532 gboolean ret = FALSE;
535 structure = gst_caps_get_structure (incaps, 0);
537 if (gst_structure_get_int (structure, "width", &width) &&
538 gst_structure_get_int (structure, "height", &height)) {
539 change_context (postproc, width, height);
547 gst_post_proc_transform_ip (GstBaseTransform * btrans, GstBuffer * in)
549 GstPostProc *postproc;
554 /* postprocess the buffer !*/
555 postproc = (GstPostProc *) btrans;
557 stride[0] = postproc->ystride;
558 stride[1] = postproc->ustride;
559 stride[2] = postproc->vstride;
560 outplane[0] = inplane[0] = GST_BUFFER_DATA (in);
561 outplane[1] = inplane[1] = outplane[0] + postproc->ysize;
562 outplane[2] = inplane[2] = outplane[1] + postproc->usize;
564 GST_DEBUG_OBJECT (postproc, "calling pp_postprocess, width:%d, height:%d",
565 postproc->width, postproc->height);
567 pp_postprocess ((const guint8**) inplane, stride, outplane, stride,
568 postproc->width, postproc->height, (int8_t*) "", 0,
569 postproc->mode, postproc->context, 0);
576 gst_post_proc_set_property (GObject * object, guint prop_id,
577 const GValue * value, GParamSpec *pspec)
579 GstPostProc *postproc = (GstPostProc *) object;
585 quality = g_value_get_uint (value);
588 postproc->autoq = g_value_get_boolean (value);
591 postproc->scope = g_value_get_enum (value);
594 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
598 /* construct common args */
599 args = postproc->autoq ? g_strdup ("autoq") : g_strdup ("");
600 switch (postproc->scope) {
604 append (&args, g_strdup ("noluma"));
607 append (&args, g_strdup ("nochrom"));
610 g_assert_not_reached ();
614 g_free (postproc->cargs);
615 postproc->cargs = args;
617 change_mode (postproc);
621 gst_post_proc_get_property (GObject * object, guint prop_id,
622 GValue * value, GParamSpec *pspec)
624 GstPostProc *postproc = (GstPostProc *) object;
628 g_value_set_uint (value, postproc->quality);
631 g_value_set_boolean (value, postproc->autoq);
634 g_value_set_enum (value, postproc->scope);
637 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
644 gst_post_proc_deblock_set_property (GObject * object, guint prop_id,
645 const GValue * value, GParamSpec *pspec)
647 GstPostProc *postproc = (GstPostProc *) object;
651 postproc->diff = g_value_get_int (value);
654 postproc->flat = g_value_get_int (value);
657 gst_post_proc_set_property (object, prop_id, value, pspec);
662 g_free (postproc->args);
663 if (postproc->diff >= 0) {
664 postproc->args = g_strdup_printf ("%d", postproc->diff);
665 if (postproc->flat >= 0)
666 append (&postproc->args, g_strdup_printf ("%d", postproc->flat));
668 postproc->args = g_strdup ("");
669 change_mode (postproc);
673 gst_post_proc_deblock_get_property ( GObject * object, guint prop_id,
674 GValue * value, GParamSpec *pspec )
676 GstPostProc *postproc = (GstPostProc *) object;
680 g_value_set_int (value, postproc->diff);
683 g_value_set_int (value, postproc->flat);
686 gst_post_proc_get_property (object, prop_id, value, pspec);
692 gst_post_proc_tmpnoise_set_property (GObject * object, guint prop_id,
693 const GValue * value, GParamSpec *pspec)
695 GstPostProc *postproc = (GstPostProc *) object;
699 postproc->t1 = g_value_get_int (value);
702 postproc->t2 = g_value_get_int (value);
705 postproc->t3 = g_value_get_int (value);
708 gst_post_proc_set_property (object, prop_id, value, pspec);
713 g_free (postproc->args);
714 if (postproc->t1 >= 0) {
715 postproc->args = g_strdup_printf ("%d", postproc->t1);
716 if (postproc->t2 >= 0) {
717 append (&postproc->args, g_strdup_printf ("%d", postproc->t2));
718 if (postproc->t3 >= 0)
719 append (&postproc->args, g_strdup_printf ("%d", postproc->t3));
722 postproc->args = g_strdup ("");
723 change_mode (postproc);
727 gst_post_proc_tmpnoise_get_property (GObject * object, guint prop_id,
728 GValue * value, GParamSpec *pspec )
730 GstPostProc *postproc = (GstPostProc *) object;
734 g_value_set_int (value, postproc->t1);
737 g_value_set_int (value, postproc->t2);
740 g_value_set_int (value, postproc->t3);
743 gst_post_proc_get_property (object, prop_id, value, pspec);
749 gst_post_proc_autolevels_set_property (GObject * object, guint prop_id,
750 const GValue * value, GParamSpec *pspec)
752 GstPostProc *postproc = (GstPostProc *) object;
756 postproc->range = g_value_get_boolean (value);
759 gst_post_proc_set_property (object, prop_id, value, pspec);
764 g_free (postproc->args);
766 postproc->args = g_strdup ("f");
768 postproc->args = g_strdup ("");
769 change_mode (postproc);
773 gst_post_proc_autolevels_get_property (GObject * object, guint prop_id,
774 GValue * value, GParamSpec *pspec )
776 GstPostProc *postproc = (GstPostProc *) object;
780 g_value_set_boolean (value, postproc->range);
783 gst_post_proc_get_property (object, prop_id, value, pspec);
789 gst_post_proc_forcequant_set_property (GObject * object, guint prop_id,
790 const GValue * value, GParamSpec *pspec)
792 GstPostProc *postproc = (GstPostProc *) object;
796 postproc->quant = g_value_get_int (value);
799 gst_post_proc_set_property (object, prop_id, value, pspec);
804 g_free (postproc->args);
805 if (postproc->quant >= 0)
806 postproc->args = g_strdup_printf ("%d", postproc->quant);
808 postproc->args = g_strdup ("");
809 change_mode (postproc);
813 gst_post_proc_forcequant_get_property (GObject * object, guint prop_id,
814 GValue * value, GParamSpec *pspec )
816 GstPostProc *postproc = (GstPostProc *) object;
820 g_value_set_int (value, postproc->quant);
823 gst_post_proc_get_property (object, prop_id, value, pspec);
830 gst_post_proc_register(GstPlugin * plugin)
832 GTypeInfo typeinfo = {
833 sizeof (GstPostProcClass),
834 (GBaseInitFunc) gst_post_proc_base_init,
836 (GClassInitFunc) gst_post_proc_class_init,
839 sizeof (GstPostProc),
841 (GInstanceInitFunc) gst_post_proc_init,
846 global_plugins = g_hash_table_new (NULL, NULL);
847 for (i = 0; filterdetails[i].shortname; i++) {
850 g_hash_table_insert (global_plugins, GINT_TO_POINTER (0),
851 GINT_TO_POINTER (i));
853 /* create type_name */
854 type_name = g_strdup_printf("postproc_%s", filterdetails[i].longname);
855 if (g_type_from_name (type_name)) {
861 type = g_type_register_static (GST_TYPE_VIDEO_FILTER, type_name,
864 g_hash_table_insert (global_plugins, GINT_TO_POINTER (type),
865 GINT_TO_POINTER (i));
867 /* register element */
868 if (!gst_element_register (plugin, type_name, GST_RANK_PRIMARY, type)) {
875 g_hash_table_remove (global_plugins, GINT_TO_POINTER (0));
881 plugin_init (GstPlugin * plugin)
883 GST_DEBUG_CATEGORY_INIT (postproc_debug, "postproc", 0,
884 "video postprocessing elements");
885 #ifndef GST_DISABLE_GST_DEBUG
886 av_log_set_callback (gst_ffmpeg_log_callback);
889 /* Register the filters */
890 gst_post_proc_register (plugin);
892 /* Now we can return the pointer to the newly created Plugin object. */
896 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
899 "postprocessing elements (" FFMPEG_SOURCE ")",
901 PACKAGE_VERSION, "GPL", "FFMpeg", "http://ffmpeg.sourceforge.net/")