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
34
#include <libpostproc/postprocess.h>
36
#include <ffmpeg/avcodec.h>
37
#include <ffmpeg/version.h>
38
#include <ffmpeg/libpostproc/postprocess.h>
42
typedef struct _PostProcDetails PostProcDetails;
44
struct _PostProcDetails {
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"},
71
typedef struct _GstPostProc GstPostProc;
75
GstVideoFilter element;
77
GstPad *sinkpad, *srcpad;
81
gint ystride, ustride, vstride;
82
gint ysize, usize, vsize;
85
pp_context_t *context;
87
/* props of various filters */
90
/* though not all needed at once,
91
* this avoids union or ugly re-use for simplicity */
97
/* argument string for pp */
101
typedef struct _GstPostProcClass GstPostProcClass;
103
struct _GstPostProcClass
105
GstVideoFilterClass parent_class;
110
/* properties for the various pp filters */
121
/* possible filter scopes */
129
#define DEFAULT_QUALITY PP_QUALITY_MAX
130
#define DEFAULT_AUTOQ FALSE
131
#define DEFAULT_SCOPE SCOPE_BOTH
133
/* deblocking props */
136
PROP_DIFF = PROP_MAX,
140
#define DEFAULT_DIFF -1
141
#define DEFAULT_FLAT -1
151
#define DEFAULT_T1 -1
152
#define DEFAULT_T2 -1
153
#define DEFAULT_T3 -1
158
PROP_RANGE = PROP_MAX
161
#define DEFAULT_RANGE FALSE
166
PROP_QUANT = PROP_MAX
169
#define DEFAULT_QUANT -1
172
/* hashtable, key = gtype, value = filterdetails index */
173
static GHashTable *global_plugins;
175
/* TODO : add support for the other format supported by libpostproc */
177
static GstStaticPadTemplate gst_post_proc_src_template =
178
GST_STATIC_PAD_TEMPLATE ("src",
181
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
184
static GstStaticPadTemplate gst_post_proc_sink_template =
185
GST_STATIC_PAD_TEMPLATE ("sink",
188
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ IYUV, I420, YV12 }"))
191
GST_DEBUG_CATEGORY (postproc_debug);
192
#define GST_CAT_DEFAULT postproc_debug
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);
199
static gboolean gst_post_proc_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
201
static GstFlowReturn gst_post_proc_transform_ip (GstBaseTransform * btrans,
204
/* static GstStateChangeReturn gst_post_proc_change_state (GstElement * element, */
205
/* GstStateChange transition); */
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);
228
static GstElementClass *parent_class = NULL;
230
#define GST_TYPE_PP_SCOPE (gst_pp_scope_get_type())
232
gst_pp_scope_get_type (void)
234
static GType pp_scope_type = 0;
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"},
243
if (!pp_scope_type) {
245
g_enum_register_static ("GstPostProcPPScope", pp_scope);
247
return pp_scope_type;
250
#ifndef GST_DISABLE_GST_DEBUG
252
gst_ffmpeg_log_callback (void * ptr, int level, const char * fmt, va_list vl)
254
GstDebugLevel gst_level;
258
gst_level = GST_LEVEL_NONE;
261
gst_level = GST_LEVEL_ERROR;
264
gst_level = GST_LEVEL_INFO;
267
gst_level = GST_LEVEL_DEBUG;
270
gst_level = GST_LEVEL_INFO;
274
gst_debug_log_valist (postproc_debug, gst_level, "", "", 0, NULL, fmt, vl);
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)
283
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);
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);
313
/* append app to *base, and places result in *base */
314
/* all input strings are free'd */
316
append (gchar ** base, gchar * app)
325
res = g_strconcat (*base, sep, app, NULL);
332
change_mode (GstPostProc * postproc )
334
GstPostProcClass * klass;
337
klass = (GstPostProcClass *) G_OBJECT_GET_CLASS (G_OBJECT (postproc));
340
pp_free_mode (postproc->mode);
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);
349
g_assert (postproc->mode);
353
gst_post_proc_base_init (GstPostProcClass * klass)
355
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
356
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
357
GstElementDetails details;
360
ppidx = GPOINTER_TO_INT (g_hash_table_lookup (global_plugins,
361
GINT_TO_POINTER (G_OBJECT_CLASS_TYPE (gobject_class))));
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);
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));
378
klass->filterid = ppidx;
382
gst_post_proc_class_init (GstPostProcClass * klass)
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);
389
parent_class = g_type_class_peek_parent (klass);
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);
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));
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));
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));
410
ppidx = klass->filterid;
411
/* per filter props */
412
if (g_strrstr (filterdetails[ppidx].longname, "deblock") != NULL &&
413
filterdetails[ppidx].longname[0] != 'x') {
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));
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));
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"))) {
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));
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));
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));
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"))) {
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));
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);
462
} else if (!(g_ascii_strcasecmp (filterdetails[ppidx].shortname, "fq"))) {
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));
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);
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);
481
gst_post_proc_init (GstPostProc * postproc)
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);
499
postproc->context = NULL;
501
postproc->height = 0;
502
postproc->ystride = 0;
503
postproc->ustride = 0;
504
postproc->vstride = 0;
511
gst_post_proc_dispose (GObject * object)
513
GstPostProc * postproc = (GstPostProc *) object;
516
pp_free_mode (postproc->mode);
517
if (postproc->context)
518
pp_free_context (postproc->context);
520
g_free (postproc->cargs);
521
postproc->cargs = NULL;
522
g_free (postproc->args);
523
postproc->args = NULL;
525
G_OBJECT_CLASS (parent_class)->dispose (object);
529
gst_post_proc_setcaps (GstBaseTransform * btrans, GstCaps * incaps,
532
GstPostProc *postproc = (GstPostProc *) (btrans);
533
GstStructure *structure;
534
gboolean ret = FALSE;
537
structure = gst_caps_get_structure (incaps, 0);
539
if (gst_structure_get_int (structure, "width", &width) &&
540
gst_structure_get_int (structure, "height", &height)) {
541
change_context (postproc, width, height);
549
gst_post_proc_transform_ip (GstBaseTransform * btrans, GstBuffer * in)
551
GstPostProc *postproc;
555
/* postprocess the buffer !*/
556
postproc = (GstPostProc *) btrans;
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;
565
GST_DEBUG_OBJECT (postproc, "calling pp_postprocess, width:%d, height:%d",
566
postproc->width, postproc->height);
568
pp_postprocess (outplane, stride, outplane, stride,
569
postproc->width, postproc->height, (int8_t*) "", 0,
570
postproc->mode, postproc->context, 0);
577
gst_post_proc_set_property (GObject * object, guint prop_id,
578
const GValue * value, GParamSpec *pspec)
580
GstPostProc *postproc = (GstPostProc *) object;
586
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");
886
#ifndef GST_DISABLE_GST_DEBUG
887
av_log_set_callback (gst_ffmpeg_log_callback);
890
/* Register the filters */
891
gst_post_proc_register (plugin);
893
/* Now we can return the pointer to the newly created Plugin object. */
897
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
900
"postprocessing elements",
902
FFMPEG_VERSION, "GPL", "FFMpeg", "http://ffmpeg.sourceforge.net/")