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>
32 #ifdef HAVE_LIBAV_UNINSTALLED
34 #include <postprocess.h>
36 #include <libavcodec/avcodec.h>
37 #include <libpostproc/postprocess.h>
41 typedef struct _PostProcDetails PostProcDetails;
43 struct _PostProcDetails
45 const char *shortname;
47 const char *description;
50 static const 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"},
71 typedef struct _GstPostProc GstPostProc;
75 GstVideoFilter element;
77 GstPad *sinkpad, *srcpad;
84 /* props of various filters */
87 /* though not all needed at once,
88 * this avoids union or ugly re-use for simplicity */
94 /* argument string for pp */
98 typedef struct _GstPostProcClass GstPostProcClass;
100 struct _GstPostProcClass
102 GstVideoFilterClass parent_class;
107 /* properties for the various pp filters */
118 /* possible filter scopes */
126 #define DEFAULT_QUALITY PP_QUALITY_MAX
127 #define DEFAULT_AUTOQ FALSE
128 #define DEFAULT_SCOPE SCOPE_BOTH
130 /* deblocking props */
133 PROP_DIFF = PROP_MAX,
137 #define DEFAULT_DIFF -1
138 #define DEFAULT_FLAT -1
148 #define DEFAULT_T1 -1
149 #define DEFAULT_T2 -1
150 #define DEFAULT_T3 -1
155 PROP_RANGE = PROP_MAX
158 #define DEFAULT_RANGE FALSE
163 PROP_QUANT = PROP_MAX
166 #define DEFAULT_QUANT -1
169 /* hashtable, key = gtype, value = filterdetails index */
170 static GHashTable *global_plugins;
172 /* TODO : add support for the other format supported by libpostproc */
174 static GstStaticPadTemplate gst_post_proc_src_template =
175 GST_STATIC_PAD_TEMPLATE ("src",
178 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ IYUV, I420, YV12, Y42B, Y41B }"))
181 static GstStaticPadTemplate gst_post_proc_sink_template =
182 GST_STATIC_PAD_TEMPLATE ("sink",
185 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ IYUV, I420, YV12, Y42B, Y41B }"))
188 GST_DEBUG_CATEGORY (postproc_debug);
189 #define GST_CAT_DEFAULT postproc_debug
191 static void gst_post_proc_class_init (GstPostProcClass * klass);
192 static void gst_post_proc_base_init (GstPostProcClass * klass);
193 static void gst_post_proc_init (GstPostProc * pproc);
194 static void gst_post_proc_dispose (GObject * object);
196 static gboolean gst_post_proc_set_info (GstVideoFilter * vfilter,
197 GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
198 GstVideoInfo * out_info);
199 static GstFlowReturn gst_post_proc_transform_frame_ip (GstVideoFilter * vfilter,
200 GstVideoFrame * frame);
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) {
242 pp_scope_type = g_enum_register_static ("GstPostProcPPScope", pp_scope);
244 return pp_scope_type;
247 #ifndef GST_DISABLE_GST_DEBUG
249 gst_ffmpeg_log_callback (void *ptr, int level, const char *fmt, va_list vl)
251 GstDebugLevel gst_level;
255 gst_level = GST_LEVEL_NONE;
258 gst_level = GST_LEVEL_ERROR;
261 gst_level = GST_LEVEL_INFO;
264 gst_level = GST_LEVEL_DEBUG;
267 gst_level = GST_LEVEL_INFO;
271 gst_debug_log_valist (postproc_debug, gst_level, "", "", 0, NULL, fmt, vl);
275 #define ROUND_UP_2(x) (((x)+1)&~1)
276 #define ROUND_UP_4(x) (((x)+3)&~3)
277 #define ROUND_UP_8(x) (((x)+7)&~7)
280 change_context (GstPostProc * postproc, gint width, gint height)
288 GST_DEBUG_OBJECT (postproc, "change_context, width:%d, height:%d",
291 if ((width != postproc->width) && (height != postproc->height)) {
292 if (postproc->context)
293 pp_free_context (postproc->context);
296 mmx_flags = orc_target_get_default_flags (orc_target_get_by_name ("mmx"));
298 orc_target_get_default_flags (orc_target_get_by_name ("altivec"));
299 ppflags = (mmx_flags & ORC_TARGET_MMX_MMX ? PP_CPU_CAPS_MMX : 0)
300 | (mmx_flags & ORC_TARGET_MMX_MMXEXT ? PP_CPU_CAPS_MMX2 : 0)
301 | (mmx_flags & ORC_TARGET_MMX_3DNOW ? PP_CPU_CAPS_3DNOW : 0)
302 | (altivec_flags & ORC_TARGET_ALTIVEC_ALTIVEC ? PP_CPU_CAPS_ALTIVEC :
308 postproc->context = pp_get_context (width, height, PP_FORMAT_420 | ppflags);
309 postproc->width = width;
310 postproc->height = height;
314 /* append app to *base, and places result in *base */
315 /* all input strings are free'd */
317 append (gchar ** base, gchar * app)
326 res = g_strconcat (*base, sep, app, NULL);
333 change_mode (GstPostProc * postproc)
335 GstPostProcClass *klass;
338 klass = (GstPostProcClass *) G_OBJECT_GET_CLASS (G_OBJECT (postproc));
341 pp_free_mode (postproc->mode);
343 name = g_strdup (filterdetails[klass->filterid].shortname);
344 append (&name, g_strdup (postproc->cargs));
345 append (&name, g_strdup (postproc->args));
346 GST_DEBUG_OBJECT (postproc, "requesting pp %s", name);
347 postproc->mode = pp_get_mode_by_name_and_quality (name, postproc->quality);
350 g_assert (postproc->mode);
354 gst_post_proc_base_init (GstPostProcClass * klass)
356 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
357 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
359 gchar *longname, *description;
361 ppidx = GPOINTER_TO_INT (g_hash_table_lookup (global_plugins,
362 GINT_TO_POINTER (G_OBJECT_CLASS_TYPE (gobject_class))));
364 longname = g_strdup_printf ("LibPostProc %s filter",
365 filterdetails[ppidx].longname);
366 description = g_strdup_printf ("LibPostProc %s",
367 filterdetails[ppidx].description);
368 gst_element_class_set_static_metadata (element_class, longname,
369 "Filter/Video", description,
370 "Edward Hervey <edward@fluendo.com>, Mark Nauwelaerts (manauw@skynet.be)");
372 g_free (description);
374 gst_element_class_add_pad_template (element_class,
375 gst_static_pad_template_get (&gst_post_proc_src_template));
376 gst_element_class_add_pad_template (element_class,
377 gst_static_pad_template_get (&gst_post_proc_sink_template));
379 klass->filterid = ppidx;
383 gst_post_proc_class_init (GstPostProcClass * klass)
385 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
386 /* GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); */
387 GstVideoFilterClass *vfilter_class = GST_VIDEO_FILTER_CLASS (klass);
390 parent_class = g_type_class_peek_parent (klass);
392 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_post_proc_set_property);
393 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_post_proc_get_property);
396 g_object_class_install_property (gobject_class, PROP_QUALITY,
397 g_param_spec_uint ("quality", "Quality",
398 "Quality level of filter (higher is better)",
399 0, PP_QUALITY_MAX, DEFAULT_QUALITY,
400 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
402 g_object_class_install_property (gobject_class, PROP_AUTOQ,
403 g_param_spec_boolean ("autoq", "AutoQ",
404 "Automatically switch filter off if CPU too slow",
405 DEFAULT_AUTOQ, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
407 g_object_class_install_property (gobject_class, PROP_SCOPE,
408 g_param_spec_enum ("scope", "Scope",
409 "Operate on chrominance and/or luminance",
410 GST_TYPE_PP_SCOPE, DEFAULT_SCOPE,
411 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
413 ppidx = klass->filterid;
414 /* per filter props */
415 if (g_strrstr (filterdetails[ppidx].longname, "deblock") != NULL &&
416 filterdetails[ppidx].longname[0] != 'x') {
418 g_object_class_install_property (gobject_class, PROP_DIFF,
419 g_param_spec_int ("difference", "Difference Factor",
420 "Higher values mean more deblocking (-1 = pp default)",
421 -1, G_MAXINT, DEFAULT_DIFF,
422 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
424 g_object_class_install_property (gobject_class, PROP_FLAT,
425 g_param_spec_int ("flatness", "Flatness Threshold",
426 "Lower values mean more deblocking (-1 = pp default)",
427 -1, G_MAXINT, DEFAULT_FLAT,
428 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
430 gobject_class->set_property =
431 GST_DEBUG_FUNCPTR (gst_post_proc_deblock_set_property);
432 gobject_class->get_property =
433 GST_DEBUG_FUNCPTR (gst_post_proc_deblock_get_property);
434 } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "tn"))) {
436 g_object_class_install_property (gobject_class, PROP_T1,
437 g_param_spec_int ("threshold-1", "Threshold One",
438 "Higher values mean stronger filtering (-1 = pp default)",
439 -1, G_MAXINT, DEFAULT_T1,
440 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
442 g_object_class_install_property (gobject_class, PROP_T2,
443 g_param_spec_int ("threshold-2", "Threshold Two",
444 "Higher values mean stronger filtering (-1 = pp default)",
445 -1, G_MAXINT, DEFAULT_T2,
446 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
448 g_object_class_install_property (gobject_class, PROP_T3,
449 g_param_spec_int ("threshold-3", "Threshold Three",
450 "Higher values mean stronger filtering (-1 = pp default)",
451 -1, G_MAXINT, DEFAULT_T3,
452 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
454 gobject_class->set_property =
455 GST_DEBUG_FUNCPTR (gst_post_proc_tmpnoise_set_property);
456 gobject_class->get_property =
457 GST_DEBUG_FUNCPTR (gst_post_proc_tmpnoise_get_property);
458 } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "al"))) {
460 g_object_class_install_property (gobject_class, PROP_RANGE,
461 g_param_spec_boolean ("fully-range", "Fully Range",
462 "Stretch luminance to (0-255)", DEFAULT_RANGE,
463 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
465 gobject_class->set_property =
466 GST_DEBUG_FUNCPTR (gst_post_proc_autolevels_set_property);
467 gobject_class->get_property =
468 GST_DEBUG_FUNCPTR (gst_post_proc_autolevels_get_property);
470 } else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "fq"))) {
472 g_object_class_install_property (gobject_class, PROP_QUANT,
473 g_param_spec_int ("quantizer", "Force Quantizer",
474 "Quantizer to use (-1 = pp default)",
475 -1, G_MAXINT, DEFAULT_QUANT,
476 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
478 gobject_class->set_property =
479 GST_DEBUG_FUNCPTR (gst_post_proc_forcequant_set_property);
480 gobject_class->get_property =
481 GST_DEBUG_FUNCPTR (gst_post_proc_forcequant_get_property);
484 gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_post_proc_dispose);
486 vfilter_class->set_info = GST_DEBUG_FUNCPTR (gst_post_proc_set_info);
487 vfilter_class->transform_frame_ip =
488 GST_DEBUG_FUNCPTR (gst_post_proc_transform_frame_ip);
492 gst_post_proc_init (GstPostProc * postproc)
495 postproc->quality = DEFAULT_QUALITY;
496 postproc->autoq = DEFAULT_AUTOQ;
497 postproc->scope = DEFAULT_SCOPE;
498 postproc->diff = DEFAULT_DIFF;
499 postproc->flat = DEFAULT_FLAT;
500 postproc->quant = DEFAULT_QUANT;
501 postproc->t1 = DEFAULT_T1;
502 postproc->t2 = DEFAULT_T2;
503 postproc->t3 = DEFAULT_T3;
504 postproc->range = DEFAULT_RANGE;
505 postproc->mode = NULL;
506 postproc->cargs = g_strdup ("");
507 postproc->args = g_strdup ("");
508 change_mode (postproc);
510 postproc->context = NULL;
512 postproc->height = 0;
516 gst_post_proc_dispose (GObject * object)
518 GstPostProc *postproc = (GstPostProc *) object;
521 pp_free_mode (postproc->mode);
522 if (postproc->context)
523 pp_free_context (postproc->context);
525 g_free (postproc->cargs);
526 postproc->cargs = NULL;
527 g_free (postproc->args);
528 postproc->args = NULL;
530 G_OBJECT_CLASS (parent_class)->dispose (object);
534 gst_post_proc_set_info (GstVideoFilter * vfilter, GstCaps * incaps,
535 GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
537 GstPostProc *postproc = (GstPostProc *) (vfilter);
539 change_context (postproc, in_info->width, in_info->height);
545 gst_post_proc_transform_frame_ip (GstVideoFilter * vfilter,
546 GstVideoFrame * frame)
548 GstPostProc *postproc;
554 /* postprocess the buffer ! */
555 postproc = (GstPostProc *) vfilter;
557 stride[0] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
558 stride[1] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 1);
559 stride[2] = GST_VIDEO_FRAME_COMP_STRIDE (frame, 2);
560 outplane[0] = inplane[0] = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
561 outplane[1] = inplane[1] = GST_VIDEO_FRAME_COMP_DATA (frame, 1);
562 outplane[2] = inplane[2] = GST_VIDEO_FRAME_COMP_DATA (frame, 2);
564 width = GST_VIDEO_FRAME_WIDTH (frame);
565 height = GST_VIDEO_FRAME_HEIGHT (frame);
567 GST_DEBUG_OBJECT (postproc, "calling pp_postprocess, width:%d, height:%d",
570 pp_postprocess ((const guint8 **) inplane, stride, outplane, stride,
571 width, height, (int8_t *) "", 0, postproc->mode, postproc->context, 0);
578 gst_post_proc_set_property (GObject * object, guint prop_id,
579 const GValue * value, GParamSpec * pspec)
581 GstPostProc *postproc = (GstPostProc *) object;
586 postproc->quality = g_value_get_uint (value);
589 postproc->autoq = g_value_get_boolean (value);
592 postproc->scope = g_value_get_enum (value);
595 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
599 /* construct common args */
600 args = postproc->autoq ? g_strdup ("autoq") : g_strdup ("");
601 switch (postproc->scope) {
605 append (&args, g_strdup ("noluma"));
608 append (&args, g_strdup ("nochrom"));
611 g_assert_not_reached ();
615 g_free (postproc->cargs);
616 postproc->cargs = args;
618 change_mode (postproc);
622 gst_post_proc_get_property (GObject * object, guint prop_id,
623 GValue * value, GParamSpec * pspec)
625 GstPostProc *postproc = (GstPostProc *) object;
629 g_value_set_uint (value, postproc->quality);
632 g_value_set_boolean (value, postproc->autoq);
635 g_value_set_enum (value, postproc->scope);
638 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
645 gst_post_proc_deblock_set_property (GObject * object, guint prop_id,
646 const GValue * value, GParamSpec * pspec)
648 GstPostProc *postproc = (GstPostProc *) object;
652 postproc->diff = g_value_get_int (value);
655 postproc->flat = g_value_get_int (value);
658 gst_post_proc_set_property (object, prop_id, value, pspec);
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));
669 postproc->args = g_strdup ("");
670 change_mode (postproc);
674 gst_post_proc_deblock_get_property (GObject * object, guint prop_id,
675 GValue * value, GParamSpec * pspec)
677 GstPostProc *postproc = (GstPostProc *) object;
681 g_value_set_int (value, postproc->diff);
684 g_value_set_int (value, postproc->flat);
687 gst_post_proc_get_property (object, prop_id, value, pspec);
693 gst_post_proc_tmpnoise_set_property (GObject * object, guint prop_id,
694 const GValue * value, GParamSpec * pspec)
696 GstPostProc *postproc = (GstPostProc *) object;
700 postproc->t1 = g_value_get_int (value);
703 postproc->t2 = g_value_get_int (value);
706 postproc->t3 = g_value_get_int (value);
709 gst_post_proc_set_property (object, prop_id, value, pspec);
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));
723 postproc->args = g_strdup ("");
724 change_mode (postproc);
728 gst_post_proc_tmpnoise_get_property (GObject * object, guint prop_id,
729 GValue * value, GParamSpec * pspec)
731 GstPostProc *postproc = (GstPostProc *) object;
735 g_value_set_int (value, postproc->t1);
738 g_value_set_int (value, postproc->t2);
741 g_value_set_int (value, postproc->t3);
744 gst_post_proc_get_property (object, prop_id, value, pspec);
750 gst_post_proc_autolevels_set_property (GObject * object, guint prop_id,
751 const GValue * value, GParamSpec * pspec)
753 GstPostProc *postproc = (GstPostProc *) object;
757 postproc->range = g_value_get_boolean (value);
760 gst_post_proc_set_property (object, prop_id, value, pspec);
765 g_free (postproc->args);
767 postproc->args = g_strdup ("f");
769 postproc->args = g_strdup ("");
770 change_mode (postproc);
774 gst_post_proc_autolevels_get_property (GObject * object, guint prop_id,
775 GValue * value, GParamSpec * pspec)
777 GstPostProc *postproc = (GstPostProc *) object;
781 g_value_set_boolean (value, postproc->range);
784 gst_post_proc_get_property (object, prop_id, value, pspec);
790 gst_post_proc_forcequant_set_property (GObject * object, guint prop_id,
791 const GValue * value, GParamSpec * pspec)
793 GstPostProc *postproc = (GstPostProc *) object;
797 postproc->quant = g_value_get_int (value);
800 gst_post_proc_set_property (object, prop_id, value, pspec);
805 g_free (postproc->args);
806 if (postproc->quant >= 0)
807 postproc->args = g_strdup_printf ("%d", postproc->quant);
809 postproc->args = g_strdup ("");
810 change_mode (postproc);
814 gst_post_proc_forcequant_get_property (GObject * object, guint prop_id,
815 GValue * value, GParamSpec * pspec)
817 GstPostProc *postproc = (GstPostProc *) object;
821 g_value_set_int (value, postproc->quant);
824 gst_post_proc_get_property (object, prop_id, value, pspec);
831 gst_post_proc_register (GstPlugin * plugin)
833 GTypeInfo typeinfo = {
834 sizeof (GstPostProcClass),
835 (GBaseInitFunc) gst_post_proc_base_init,
837 (GClassInitFunc) gst_post_proc_class_init,
840 sizeof (GstPostProc),
842 (GInstanceInitFunc) gst_post_proc_init,
847 global_plugins = g_hash_table_new (NULL, NULL);
848 for (i = 0; filterdetails[i].shortname; i++) {
851 g_hash_table_insert (global_plugins, GINT_TO_POINTER (0),
852 GINT_TO_POINTER (i));
854 /* create type_name */
855 type_name = g_strdup_printf ("postproc_%s", filterdetails[i].longname);
856 if (g_type_from_name (type_name)) {
862 type = g_type_register_static (GST_TYPE_VIDEO_FILTER, type_name,
865 g_hash_table_insert (global_plugins, GINT_TO_POINTER (type),
866 GINT_TO_POINTER (i));
868 /* register element */
869 if (!gst_element_register (plugin, type_name, GST_RANK_PRIMARY, type)) {
876 g_hash_table_remove (global_plugins, GINT_TO_POINTER (0));
882 plugin_init (GstPlugin * plugin)
884 GST_DEBUG_CATEGORY_INIT (postproc_debug, "postproc", 0,
885 "video postprocessing elements");
891 #ifndef GST_DISABLE_GST_DEBUG
892 av_log_set_callback (gst_ffmpeg_log_callback);
895 /* Register the filters */
896 gst_post_proc_register (plugin);
898 /* Now we can return the pointer to the newly created Plugin object. */
902 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
905 "postprocessing elements (" LIBAV_SOURCE ")",
906 plugin_init, PACKAGE_VERSION, "GPL", "libav", "http://www.libav.org")