summaryrefslogtreecommitdiffstats
path: root/gst/deinterlace2/gstdeinterlace2.c
diff options
context:
space:
mode:
authorSebastian Dröge <slomo@circular-chaos.org>2008-07-05 16:47:32 +0000
committerSebastian Dröge <slomo@circular-chaos.org>2008-07-05 16:47:32 +0000
commitd7c49f75d6dace82b2038a2a5c647822059dd6ed (patch)
treea5550cee43baa7ad41555c1c2b77ba36f17e60fd /gst/deinterlace2/gstdeinterlace2.c
parent8fccf53fc2d070a4938ceb05b164f4a273388b20 (diff)
downloadgst-plugins-bad-d7c49f75d6dace82b2038a2a5c647822059dd6ed.tar.gz
gst-plugins-bad-d7c49f75d6dace82b2038a2a5c647822059dd6ed.tar.bz2
gst-plugins-bad-d7c49f75d6dace82b2038a2a5c647822059dd6ed.zip
gst/deinterlace2/: Use a GstObject subtype for the deinterlacing methods and export the different settings for each d...
Original commit message from CVS: * gst/deinterlace2/Makefile.am: * gst/deinterlace2/gstdeinterlace2.c: (gst_deinterlace_method_class_init), (gst_deinterlace_method_init), (gst_deinterlace_method_deinterlace_frame), (gst_deinterlace_method_get_fields_required), (gst_deinterlace2_methods_get_type), (_do_init), (gst_deinterlace2_set_method), (gst_deinterlace2_class_init), (gst_deinterlace2_child_proxy_get_child_by_index), (gst_deinterlace2_child_proxy_get_children_count), (gst_deinterlace2_child_proxy_interface_init), (gst_deinterlace2_init), (gst_deinterlace2_finalize), (gst_deinterlace2_chain), (gst_deinterlace2_src_query): * gst/deinterlace2/gstdeinterlace2.h: * gst/deinterlace2/tvtime/greedy.c: (deinterlace_greedy_packed422_scanline_c), (deinterlace_greedy_packed422_scanline_mmx), (deinterlace_greedy_packed422_scanline_mmxext), (deinterlace_frame_di_greedy), (gst_deinterlace_method_greedy_l_set_property), (gst_deinterlace_method_greedy_l_get_property), (gst_deinterlace_method_greedy_l_class_init), (gst_deinterlace_method_greedy_l_init): * gst/deinterlace2/tvtime/greedyh.asm: * gst/deinterlace2/tvtime/greedyh.c: (greedyDScaler_C), (deinterlace_frame_di_greedyh), (gst_deinterlace_method_greedy_h_set_property), (gst_deinterlace_method_greedy_h_get_property), (gst_deinterlace_method_greedy_h_class_init), (gst_deinterlace_method_greedy_h_init): * gst/deinterlace2/tvtime/greedyh.h: * gst/deinterlace2/tvtime/plugins.h: * gst/deinterlace2/tvtime/tomsmocomp.c: (gst_deinterlace_method_tomsmocomp_set_property), (gst_deinterlace_method_tomsmocomp_get_property), (gst_deinterlace_method_tomsmocomp_class_init), (gst_deinterlace_method_tomsmocomp_init): * gst/deinterlace2/tvtime/tomsmocomp.h: * gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc: * gst/deinterlace2/tvtime/vfir.c: (deinterlace_frame_vfir), (gst_deinterlace_method_vfir_class_init), (gst_deinterlace_method_vfir_init): Use a GstObject subtype for the deinterlacing methods and export the different settings for each deinterlacing method via GObject properties. Implement GstChildProxy interface to allow access to the used deinterlacing method and to allow adjusting the different settings. Move global variables of the tomsmocomp deinterlacing method into function local variables to make it possible to use this deinterlacing method from different instances.
Diffstat (limited to 'gst/deinterlace2/gstdeinterlace2.c')
-rw-r--r--gst/deinterlace2/gstdeinterlace2.c263
1 files changed, 179 insertions, 84 deletions
diff --git a/gst/deinterlace2/gstdeinterlace2.c b/gst/deinterlace2/gstdeinterlace2.c
index e42afaba..4103cfb6 100644
--- a/gst/deinterlace2/gstdeinterlace2.c
+++ b/gst/deinterlace2/gstdeinterlace2.c
@@ -1,7 +1,7 @@
/*
* GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de>
- * Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
+ * Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -49,25 +49,56 @@ enum
ARG_FIELD_LAYOUT
};
-#define GST_TYPE_DEINTERLACE2_METHOD (gst_deinterlace2_method_get_type ())
+G_DEFINE_TYPE (GstDeinterlaceMethod, gst_deinterlace_method, GST_TYPE_OBJECT);
+
+static void
+gst_deinterlace_method_class_init (GstDeinterlaceMethodClass * klass)
+{
+ klass->available = TRUE;
+}
+
+static void
+gst_deinterlace_method_init (GstDeinterlaceMethod * self)
+{
+
+}
+
+static void
+gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self,
+ GstDeinterlace2 * object)
+{
+ GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+
+ klass->deinterlace_frame (self, object);
+}
+
+static gint
+gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self)
+{
+ GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+
+ return klass->fields_required;
+}
+
+#define GST_TYPE_DEINTERLACE2_METHODS (gst_deinterlace2_methods_get_type ())
static GType
-gst_deinterlace2_method_get_type (void)
+gst_deinterlace2_methods_get_type (void)
{
- static GType deinterlace2_method_type = 0;
+ static GType deinterlace2_methods_type = 0;
- static const GEnumValue method_types[] = {
- {GST_DEINTERLACE2_TOM, "Toms Motion Compensation", "tomsmc"},
+ static const GEnumValue methods_types[] = {
+ {GST_DEINTERLACE2_TOMSMOCOMP, "Toms Motion Compensation", "tomsmocomp"},
{GST_DEINTERLACE2_GREEDY_H, "Greedy High Motion", "greedyh"},
{GST_DEINTERLACE2_GREEDY_L, "Greedy Low Motion", "greedyl"},
{GST_DEINTERLACE2_VFIR, "Vertical Blur", "vfir"},
{0, NULL, NULL},
};
- if (!deinterlace2_method_type) {
- deinterlace2_method_type =
- g_enum_register_static ("GstDeinterlace2Methods", method_types);
+ if (!deinterlace2_methods_type) {
+ deinterlace2_methods_type =
+ g_enum_register_static ("GstDeinterlace2Methods", methods_types);
}
- return deinterlace2_method_type;
+ return deinterlace2_methods_type;
}
#define GST_TYPE_DEINTERLACE2_FIELDS (gst_deinterlace2_fields_get_type ())
@@ -141,8 +172,66 @@ static const GstQueryType *gst_deinterlace2_src_query_types (GstPad * pad);
static void gst_deinterlace2_reset (GstDeinterlace2 * object);
-GST_BOILERPLATE (GstDeinterlace2, gst_deinterlace2, GstElement,
- GST_TYPE_ELEMENT);
+static void gst_deinterlace2_child_proxy_interface_init (gpointer g_iface,
+ gpointer iface_data);
+
+static void
+_do_init (GType object_type)
+{
+ const GInterfaceInfo child_proxy_interface_info = {
+ (GInterfaceInitFunc) gst_deinterlace2_child_proxy_interface_init,
+ NULL, /* interface_finalize */
+ NULL /* interface_data */
+ };
+
+ g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
+ &child_proxy_interface_info);
+}
+
+GST_BOILERPLATE_FULL (GstDeinterlace2, gst_deinterlace2, GstElement,
+ GST_TYPE_ELEMENT, _do_init);
+
+static void
+gst_deinterlace2_set_method (GstDeinterlace2 * object,
+ GstDeinterlace2Methods method)
+{
+
+ if (object->method) {
+ gst_child_proxy_child_removed (GST_OBJECT (object),
+ GST_OBJECT (object->method));
+ gst_object_unparent (GST_OBJECT (object->method));
+ object->method = NULL;
+ }
+
+ switch (method) {
+ case GST_DEINTERLACE2_TOMSMOCOMP:
+ object->method = g_object_new (GST_TYPE_DEINTERLACE_TOMSMOCOMP, NULL);
+ break;
+ case GST_DEINTERLACE2_GREEDY_H:
+ object->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_H, NULL);
+ break;
+ case GST_DEINTERLACE2_GREEDY_L:
+ object->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_L, NULL);
+ break;
+ case GST_DEINTERLACE2_VFIR:
+ object->method = g_object_new (GST_TYPE_DEINTERLACE_VFIR, NULL);
+ break;
+ default:
+ GST_WARNING ("Invalid Deinterlacer Method");
+ return;
+ }
+
+ object->method_id = method;
+
+ gst_object_set_name (GST_OBJECT (object->method), "method");
+ gst_object_set_parent (GST_OBJECT (object->method), GST_OBJECT (object));
+ gst_child_proxy_child_added (GST_OBJECT (object),
+ GST_OBJECT (object->method));
+
+ /* TODO: if current method requires less fields in the history,
+ pop the diff from field_history.
+ */
+}
static void
gst_deinterlace2_base_init (gpointer klass)
@@ -177,8 +266,9 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
g_param_spec_enum ("method",
"Method",
"Deinterlace Method",
- GST_TYPE_DEINTERLACE2_METHOD,
- GST_DEINTERLACE2_TOM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
+ GST_TYPE_DEINTERLACE2_METHODS,
+ GST_DEINTERLACE2_TOMSMOCOMP,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (gobject_class, ARG_FIELDS,
@@ -202,6 +292,33 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
GST_DEBUG_FUNCPTR (gst_deinterlace2_change_state);
}
+static GstObject *
+gst_deinterlace2_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
+ guint index)
+{
+ GstDeinterlace2 *self = GST_DEINTERLACE2 (child_proxy);
+
+ g_return_val_if_fail (index == 0, NULL);
+
+ return gst_object_ref (self->method);
+}
+
+static guint
+gst_deinterlace2_child_proxy_get_children_count (GstChildProxy * child_proxy)
+{
+ return 1;
+}
+
+static void
+gst_deinterlace2_child_proxy_interface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ GstChildProxyInterface *iface = g_iface;
+
+ iface->get_child_by_index = gst_deinterlace2_child_proxy_get_child_by_index;
+ iface->get_children_count = gst_deinterlace2_child_proxy_get_children_count;
+}
+
static void
gst_deinterlace2_init (GstDeinterlace2 * object, GstDeinterlace2Class * klass)
{
@@ -231,9 +348,7 @@ gst_deinterlace2_init (GstDeinterlace2 * object, GstDeinterlace2Class * klass)
gst_element_no_more_pads (GST_ELEMENT (object));
- object->cpu_feature_flags = oil_cpu_get_flags ();
-
- object->method = dscaler_tomsmocomp_get_method ();
+ gst_deinterlace2_set_method (object, GST_DEINTERLACE2_TOMSMOCOMP);
object->field_layout = GST_DEINTERLACE2_LAYOUT_AUTO;
object->fields = GST_DEINTERLACE2_ALL;
@@ -276,37 +391,6 @@ gst_deinterlace2_reset (GstDeinterlace2 * object)
}
static void
-gst_deinterlace2_set_method (GstDeinterlace2 * object,
- GstDeinterlace2Methods method)
-{
-
- switch (method) {
- case GST_DEINTERLACE2_TOM:
- object->method_id = method;
- object->method = dscaler_tomsmocomp_get_method ();
- break;
- case GST_DEINTERLACE2_GREEDY_H:
- object->method_id = method;
- object->method = dscaler_greedyh_get_method ();
- break;
- case GST_DEINTERLACE2_GREEDY_L:
- object->method_id = method;
- object->method = dscaler_greedyl_get_method ();
- break;
- case GST_DEINTERLACE2_VFIR:
- object->method_id = method;
- object->method = dscaler_vfir_get_method ();
- break;
- default:
- GST_WARNING ("Invalid Deinterlacer Method");
- }
-
- /* TODO: if current method requires less fields in the history,
- pop the diff from field_history.
- */
-}
-
-static void
gst_deinterlace2_set_property (GObject * _object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
@@ -367,7 +451,14 @@ gst_deinterlace2_get_property (GObject * _object, guint prop_id,
static void
gst_deinterlace2_finalize (GObject * object)
{
- gst_deinterlace2_reset (GST_DEINTERLACE2 (object));
+ GstDeinterlace2 *self = GST_DEINTERLACE2 (object);
+
+ gst_deinterlace2_reset (self);
+
+ if (self->method) {
+ gst_object_unparent (GST_OBJECT (self->method));
+ self->method = NULL;
+ }
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -456,6 +547,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
GstDeinterlace2 *object = NULL;
GstClockTime timestamp;
GstFlowReturn ret = GST_FLOW_OK;
+ gint fields_required = 0;
object = GST_DEINTERLACE2 (GST_PAD_PARENT (pad));
@@ -464,9 +556,11 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
if (object->method != NULL) {
int cur_field_idx = 0;
+ fields_required =
+ gst_deinterlace_method_get_fields_required (object->method);
/* Not enough fields in the history */
- if (object->history_count < object->method->fields_required + 1) {
+ if (object->history_count < fields_required + 1) {
/* TODO: do bob or just forward frame */
GST_DEBUG ("HistoryCount=%d", object->history_count);
return GST_FLOW_OK;
@@ -479,7 +573,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
if (object->fields == GST_DEINTERLACE2_BF)
GST_DEBUG ("Bottom fields");
- cur_field_idx = object->history_count - object->method->fields_required;
+ cur_field_idx = object->history_count - fields_required;
if ((object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP
&& object->fields == GST_DEINTERLACE2_TF) ||
@@ -494,25 +588,23 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
return ret;
/* do magic calculus */
- if (object->method->deinterlace_frame != NULL) {
- object->method->deinterlace_frame (object);
+ gst_deinterlace_method_deinterlace_frame (object->method, object);
- buf = gst_deinterlace2_pop_history (object);
- timestamp = GST_BUFFER_TIMESTAMP (buf);
- gst_buffer_unref (buf);
+ buf = gst_deinterlace2_pop_history (object);
+ timestamp = GST_BUFFER_TIMESTAMP (buf);
+ gst_buffer_unref (buf);
- GST_BUFFER_TIMESTAMP (object->out_buf) = timestamp;
+ GST_BUFFER_TIMESTAMP (object->out_buf) = timestamp;
+ GST_BUFFER_DURATION (object->out_buf) =
+ GST_SECOND / object->frame_rate_d / object->frame_rate_n;
+ if (object->fields == GST_DEINTERLACE2_ALL)
GST_BUFFER_DURATION (object->out_buf) =
- GST_SECOND / object->frame_rate_d / object->frame_rate_n;
- if (object->fields == GST_DEINTERLACE2_ALL)
- GST_BUFFER_DURATION (object->out_buf) =
- GST_BUFFER_DURATION (object->out_buf) / 2;
-
- ret = gst_pad_push (object->srcpad, object->out_buf);
- object->out_buf = NULL;
- if (ret != GST_FLOW_OK)
- return ret;
- }
+ GST_BUFFER_DURATION (object->out_buf) / 2;
+
+ ret = gst_pad_push (object->srcpad, object->out_buf);
+ object->out_buf = NULL;
+ if (ret != GST_FLOW_OK)
+ return ret;
}
/* no calculation done: remove excess field */
else if (object->field_history[cur_field_idx].flags ==
@@ -522,7 +614,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
gst_buffer_unref (buf);
}
- cur_field_idx = object->history_count - object->method->fields_required;
+ cur_field_idx = object->history_count - fields_required;
/* deinterlace bottom_field */
if ((object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM
@@ -538,26 +630,24 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
return ret;
/* do magic calculus */
- if (object->method->deinterlace_frame != NULL) {
- object->method->deinterlace_frame (object);
+ gst_deinterlace_method_deinterlace_frame (object->method, object);
- buf = gst_deinterlace2_pop_history (object);
- timestamp = GST_BUFFER_TIMESTAMP (buf);
- gst_buffer_unref (buf);
+ buf = gst_deinterlace2_pop_history (object);
+ timestamp = GST_BUFFER_TIMESTAMP (buf);
+ gst_buffer_unref (buf);
- GST_BUFFER_TIMESTAMP (object->out_buf) = timestamp;
+ GST_BUFFER_TIMESTAMP (object->out_buf) = timestamp;
+ GST_BUFFER_DURATION (object->out_buf) =
+ GST_SECOND / object->frame_rate_d / object->frame_rate_n;
+ if (object->fields == GST_DEINTERLACE2_ALL)
GST_BUFFER_DURATION (object->out_buf) =
- GST_SECOND / object->frame_rate_d / object->frame_rate_n;
- if (object->fields == GST_DEINTERLACE2_ALL)
- GST_BUFFER_DURATION (object->out_buf) =
- GST_BUFFER_DURATION (object->out_buf) / 2;
+ GST_BUFFER_DURATION (object->out_buf) / 2;
- ret = gst_pad_push (object->srcpad, object->out_buf);
- object->out_buf = NULL;
+ ret = gst_pad_push (object->srcpad, object->out_buf);
+ object->out_buf = NULL;
- if (ret != GST_FLOW_OK)
- return ret;
- }
+ if (ret != GST_FLOW_OK)
+ return ret;
}
/* no calculation done: remove excess field */
else if (object->field_history[cur_field_idx].flags ==
@@ -757,6 +847,11 @@ gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
if ((peer = gst_pad_get_peer (object->sinkpad))) {
if ((res = gst_pad_query (peer, query))) {
GstClockTime latency;
+ gint fields_required = 0;
+
+ if (object->method)
+ fields_required =
+ gst_deinterlace_method_get_fields_required (object->method);
gst_query_parse_latency (query, &live, &min, &max);
@@ -766,7 +861,7 @@ gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
/* add our own latency */
latency =
- gst_util_uint64_scale (object->method->fields_required *
+ gst_util_uint64_scale (fields_required *
GST_SECOND, object->frame_rate_d, object->frame_rate_n);
latency /= 2;