summaryrefslogtreecommitdiffstats
path: root/gst/deinterlace2/gstdeinterlace2.c
diff options
context:
space:
mode:
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;