mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 15:27:07 +00:00
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.
This commit is contained in:
parent
8fccf53fc2
commit
d7c49f75d6
13 changed files with 762 additions and 469 deletions
54
ChangeLog
54
ChangeLog
|
@ -1,3 +1,57 @@
|
|||
2008-07-05 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
|
||||
* 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.
|
||||
|
||||
2008-07-05 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||
|
||||
* gst/deinterlace2/tvtime/greedyh.asm:
|
||||
|
|
|
@ -17,7 +17,6 @@ noinst_HEADERS = \
|
|||
gstdeinterlace2.h \
|
||||
tvtime/mmx.h \
|
||||
tvtime/sse.h \
|
||||
tvtime/greedyh.h \
|
||||
tvtime/greedyh.asm \
|
||||
tvtime/greedyhmacros.h \
|
||||
tvtime/plugins.h \
|
||||
|
|
|
@ -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 ())
|
||||
static GType
|
||||
gst_deinterlace2_method_get_type (void)
|
||||
{
|
||||
static GType deinterlace2_method_type = 0;
|
||||
G_DEFINE_TYPE (GstDeinterlaceMethod, gst_deinterlace_method, GST_TYPE_OBJECT);
|
||||
|
||||
static const GEnumValue method_types[] = {
|
||||
{GST_DEINTERLACE2_TOM, "Toms Motion Compensation", "tomsmc"},
|
||||
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_methods_get_type (void)
|
||||
{
|
||||
static GType deinterlace2_methods_type = 0;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -275,37 +390,6 @@ gst_deinterlace2_reset (GstDeinterlace2 * object)
|
|||
gst_deinterlace2_reset_history (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;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -45,29 +45,40 @@ G_BEGIN_DECLS
|
|||
typedef struct _GstDeinterlace2 GstDeinterlace2;
|
||||
typedef struct _GstDeinterlace2Class GstDeinterlace2Class;
|
||||
|
||||
typedef struct deinterlace_setting_s deinterlace_setting_t;
|
||||
typedef struct deinterlace_method_s deinterlace_method_t;
|
||||
#define GST_TYPE_DEINTERLACE_METHOD (gst_deinterlace_method_get_type ())
|
||||
#define GST_IS_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD))
|
||||
#define GST_IS_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD))
|
||||
#define GST_DEINTERLACE_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass))
|
||||
#define GST_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethod))
|
||||
#define GST_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass))
|
||||
#define GST_DEINTERLACE_METHOD_CAST(obj) ((GstDeinterlaceMethod*)(obj))
|
||||
|
||||
typedef void (*deinterlace_frame_t) (GstDeinterlace2 * object);
|
||||
typedef struct _GstDeinterlaceMethod GstDeinterlaceMethod;
|
||||
typedef struct _GstDeinterlaceMethodClass GstDeinterlaceMethodClass;
|
||||
|
||||
/*
|
||||
* This structure defines the deinterlacer plugin.
|
||||
*/
|
||||
struct deinterlace_method_s
|
||||
{
|
||||
int version;
|
||||
const char *name;
|
||||
const char *short_name;
|
||||
int fields_required;
|
||||
int accelrequired;
|
||||
int doscalerbob;
|
||||
int numsettings;
|
||||
deinterlace_setting_t *settings;
|
||||
int scanlinemode;
|
||||
deinterlace_frame_t deinterlace_frame;
|
||||
const char *description[10];
|
||||
|
||||
struct _GstDeinterlaceMethod {
|
||||
GstObject parent;
|
||||
};
|
||||
|
||||
struct _GstDeinterlaceMethodClass {
|
||||
GstObjectClass parent_class;
|
||||
guint fields_required;
|
||||
guint latency;
|
||||
|
||||
gboolean available;
|
||||
|
||||
void (*deinterlace_frame) (GstDeinterlaceMethod *self, GstDeinterlace2 * object);
|
||||
|
||||
const gchar *name;
|
||||
const gchar *nick;
|
||||
};
|
||||
|
||||
GType gst_deinterlace_method_get_type (void);
|
||||
|
||||
#define MAX_FIELD_HISTORY 10
|
||||
|
||||
#define PICTURE_PROGRESSIVE 0
|
||||
|
@ -75,8 +86,6 @@ struct deinterlace_method_s
|
|||
#define PICTURE_INTERLACED_TOP 2
|
||||
#define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP)
|
||||
|
||||
typedef void (MEMCPY_FUNC) (void *pOutput, const void *pInput, size_t nSize);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* pointer to the start of data for this field */
|
||||
|
@ -87,7 +96,7 @@ typedef struct
|
|||
|
||||
typedef enum
|
||||
{
|
||||
GST_DEINTERLACE2_TOM,
|
||||
GST_DEINTERLACE2_TOMSMOCOMP,
|
||||
GST_DEINTERLACE2_GREEDY_H,
|
||||
GST_DEINTERLACE2_GREEDY_L,
|
||||
GST_DEINTERLACE2_VFIR
|
||||
|
@ -115,7 +124,6 @@ struct _GstDeinterlace2
|
|||
|
||||
guint history_count;
|
||||
|
||||
guint cpu_feature_flags;
|
||||
GstDeinterlace2FieldLayout field_layout;
|
||||
|
||||
guint frame_size;
|
||||
|
@ -124,7 +132,7 @@ struct _GstDeinterlace2
|
|||
GstDeinterlace2Fields fields;
|
||||
|
||||
GstDeinterlace2Methods method_id;
|
||||
deinterlace_method_t *method;
|
||||
GstDeinterlaceMethod *method;
|
||||
|
||||
/* The most recent pictures
|
||||
PictureHistory[0] is always the most recent.
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* Copyright (c) 2000 Tom Barry All rights reserved.
|
||||
* mmx.h port copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>.
|
||||
*
|
||||
* 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
|
||||
* License as published by the Free Software Foundation; either
|
||||
|
@ -35,6 +37,30 @@
|
|||
#include "gstdeinterlace2.h"
|
||||
#include <string.h>
|
||||
|
||||
#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ())
|
||||
#define GST_IS_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L))
|
||||
#define GST_IS_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L))
|
||||
#define GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass))
|
||||
#define GST_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyL))
|
||||
#define GST_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass))
|
||||
#define GST_DEINTERLACE_METHOD_GREEDY_L_CAST(obj) ((GstDeinterlaceMethodGreedyL*)(obj))
|
||||
|
||||
GType gst_deinterlace_method_greedy_l_get_type (void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstDeinterlaceMethod parent;
|
||||
|
||||
guint max_comb;
|
||||
} GstDeinterlaceMethodGreedyL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstDeinterlaceMethodClass parent_class;
|
||||
void (*scanline) (GstDeinterlaceMethodGreedyL * self, uint8_t * L2,
|
||||
uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size);
|
||||
} GstDeinterlaceMethodGreedyLClass;
|
||||
|
||||
// This is a simple lightweight DeInterlace method that uses little CPU time
|
||||
// but gives very good results for low or intermedite motion.
|
||||
// It defers frames by one field, but that does not seem to produce noticeable
|
||||
|
@ -47,13 +73,13 @@
|
|||
// I'd intended this to be part of a larger more elaborate method added to
|
||||
// Blended Clip but this give too good results for the CPU to ignore here.
|
||||
|
||||
static const int GreedyMaxComb = 15;
|
||||
|
||||
static inline void
|
||||
deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
|
||||
deinterlace_greedy_packed422_scanline_c (GstDeinterlaceMethodGreedyL * self,
|
||||
uint8_t * m0, uint8_t * t1,
|
||||
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
|
||||
{
|
||||
int avg, l2_diff, lp2_diff, max, min, best;
|
||||
guint max_comb = self->max_comb;
|
||||
|
||||
// L2 == m0
|
||||
// L1 == t1
|
||||
|
@ -74,13 +100,13 @@ deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
|
|||
max = MAX (*t1, *b1);
|
||||
min = MIN (*t1, *b1);
|
||||
|
||||
if (max < 256 - GreedyMaxComb)
|
||||
max += GreedyMaxComb;
|
||||
if (max < 256 - max_comb)
|
||||
max += max_comb;
|
||||
else
|
||||
max = 255;
|
||||
|
||||
if (min > GreedyMaxComb)
|
||||
min -= GreedyMaxComb;
|
||||
if (min > max_comb)
|
||||
min -= max_comb;
|
||||
else
|
||||
min = 0;
|
||||
|
||||
|
@ -98,22 +124,22 @@ deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
|
|||
#ifdef HAVE_CPU_I386
|
||||
#include "mmx.h"
|
||||
static void
|
||||
deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
|
||||
deinterlace_greedy_packed422_scanline_mmx (GstDeinterlaceMethodGreedyL * self,
|
||||
uint8_t * m0, uint8_t * t1,
|
||||
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
|
||||
{
|
||||
mmx_t MaxComb;
|
||||
|
||||
mmx_t ShiftMask;
|
||||
|
||||
// How badly do we let it weave? 0-255
|
||||
MaxComb.ub[0] = GreedyMaxComb;
|
||||
MaxComb.ub[1] = GreedyMaxComb;
|
||||
MaxComb.ub[2] = GreedyMaxComb;
|
||||
MaxComb.ub[3] = GreedyMaxComb;
|
||||
MaxComb.ub[4] = GreedyMaxComb;
|
||||
MaxComb.ub[5] = GreedyMaxComb;
|
||||
MaxComb.ub[6] = GreedyMaxComb;
|
||||
MaxComb.ub[7] = GreedyMaxComb;
|
||||
MaxComb.ub[0] = self->max_comb;
|
||||
MaxComb.ub[1] = self->max_comb;
|
||||
MaxComb.ub[2] = self->max_comb;
|
||||
MaxComb.ub[3] = self->max_comb;
|
||||
MaxComb.ub[4] = self->max_comb;
|
||||
MaxComb.ub[5] = self->max_comb;
|
||||
MaxComb.ub[6] = self->max_comb;
|
||||
MaxComb.ub[7] = self->max_comb;
|
||||
|
||||
ShiftMask.ub[0] = 0x7f;
|
||||
ShiftMask.ub[1] = 0x7f;
|
||||
|
@ -207,26 +233,28 @@ deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
|
|||
}
|
||||
emms ();
|
||||
if (width > 0)
|
||||
deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
|
||||
deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output,
|
||||
width);
|
||||
}
|
||||
|
||||
#include "sse.h"
|
||||
|
||||
static void
|
||||
deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1,
|
||||
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
|
||||
deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlaceMethodGreedyL *
|
||||
self, uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2,
|
||||
uint8_t * output, int width)
|
||||
{
|
||||
mmx_t MaxComb;
|
||||
|
||||
// How badly do we let it weave? 0-255
|
||||
MaxComb.ub[0] = GreedyMaxComb;
|
||||
MaxComb.ub[1] = GreedyMaxComb;
|
||||
MaxComb.ub[2] = GreedyMaxComb;
|
||||
MaxComb.ub[3] = GreedyMaxComb;
|
||||
MaxComb.ub[4] = GreedyMaxComb;
|
||||
MaxComb.ub[5] = GreedyMaxComb;
|
||||
MaxComb.ub[6] = GreedyMaxComb;
|
||||
MaxComb.ub[7] = GreedyMaxComb;
|
||||
MaxComb.ub[0] = self->max_comb;
|
||||
MaxComb.ub[1] = self->max_comb;
|
||||
MaxComb.ub[2] = self->max_comb;
|
||||
MaxComb.ub[3] = self->max_comb;
|
||||
MaxComb.ub[4] = self->max_comb;
|
||||
MaxComb.ub[5] = self->max_comb;
|
||||
MaxComb.ub[6] = self->max_comb;
|
||||
MaxComb.ub[7] = self->max_comb;
|
||||
|
||||
// L2 == m0
|
||||
// L1 == t1
|
||||
|
@ -299,17 +327,20 @@ deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1,
|
|||
emms ();
|
||||
|
||||
if (width > 0)
|
||||
deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
|
||||
deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output,
|
||||
width);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
deinterlace_frame_di_greedy (GstDeinterlace2 * object)
|
||||
deinterlace_frame_di_greedy (GstDeinterlaceMethod * d_method,
|
||||
GstDeinterlace2 * object)
|
||||
{
|
||||
void (*func) (uint8_t * L2, uint8_t * L1, uint8_t * L3, uint8_t * L2P,
|
||||
uint8_t * Dest, int size);
|
||||
|
||||
GstDeinterlaceMethodGreedyL *self =
|
||||
GST_DEINTERLACE_METHOD_GREEDY_L (d_method);
|
||||
GstDeinterlaceMethodGreedyLClass *klass =
|
||||
GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS (self);
|
||||
int InfoIsOdd = 0;
|
||||
int Line;
|
||||
unsigned int Pitch = object->field_stride;
|
||||
|
@ -320,18 +351,6 @@ deinterlace_frame_di_greedy (GstDeinterlace2 * object)
|
|||
unsigned char *L2P; // ptr to prev Line2
|
||||
unsigned char *Dest = GST_BUFFER_DATA (object->out_buf);
|
||||
|
||||
#ifdef HAVE_CPU_I386
|
||||
if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMXEXT) {
|
||||
func = deinterlace_greedy_packed422_scanline_mmxext;
|
||||
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
|
||||
func = deinterlace_greedy_packed422_scanline_mmx;
|
||||
} else {
|
||||
func = deinterlace_greedy_packed422_scanline_c;
|
||||
}
|
||||
#else
|
||||
func = deinterlace_greedy_packed422_scanline_c;
|
||||
#endif
|
||||
|
||||
// copy first even line no matter what, and the first odd line if we're
|
||||
// processing an EVEN field. (note diff from other deint rtns.)
|
||||
|
||||
|
@ -368,7 +387,7 @@ deinterlace_frame_di_greedy (GstDeinterlace2 * object)
|
|||
}
|
||||
|
||||
for (Line = 0; Line < (object->field_height - 1); ++Line) {
|
||||
func (L2, L1, L3, L2P, Dest, object->line_length);
|
||||
klass->scanline (self, L2, L1, L3, L2P, Dest, object->line_length);
|
||||
Dest += object->output_stride;
|
||||
memcpy (Dest, L3, object->line_length);
|
||||
Dest += object->output_stride;
|
||||
|
@ -384,31 +403,84 @@ deinterlace_frame_di_greedy (GstDeinterlace2 * object)
|
|||
}
|
||||
}
|
||||
|
||||
static deinterlace_method_t greedyl_method = {
|
||||
0, //DEINTERLACE_PLUGIN_API_VERSION,
|
||||
"Motion Adaptive: Simple Detection",
|
||||
"AdaptiveSimple",
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
deinterlace_frame_di_greedy,
|
||||
{"Uses heuristics to detect motion in the input",
|
||||
"frames and reconstruct image detail where",
|
||||
"possible. Use this for high quality output",
|
||||
"even on monitors set to an arbitrary refresh",
|
||||
"rate.",
|
||||
"",
|
||||
"Simple detection uses linear interpolation",
|
||||
"where motion is detected, using a two-field",
|
||||
"buffer. This is the Greedy: Low Motion",
|
||||
"deinterlacer from DScaler."}
|
||||
|
||||
G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l,
|
||||
GST_TYPE_DEINTERLACE_METHOD);
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_MAX_COMB
|
||||
};
|
||||
|
||||
deinterlace_method_t *
|
||||
dscaler_greedyl_get_method (void)
|
||||
static void
|
||||
gst_deinterlace_method_greedy_l_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
return &greedyl_method;
|
||||
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_MAX_COMB:
|
||||
self->max_comb = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_greedy_l_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_MAX_COMB:
|
||||
g_value_set_uint (value, self->max_comb);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass *
|
||||
klass)
|
||||
{
|
||||
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
guint cpu_flags = oil_cpu_get_flags ();
|
||||
|
||||
gobject_class->set_property = gst_deinterlace_method_greedy_l_set_property;
|
||||
gobject_class->get_property = gst_deinterlace_method_greedy_l_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_MAX_COMB,
|
||||
g_param_spec_uint ("max-comb",
|
||||
"Max comb",
|
||||
"Max Comb", 0, 255, 15, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||
);
|
||||
|
||||
dim_class->fields_required = 4;
|
||||
dim_class->deinterlace_frame = deinterlace_frame_di_greedy;
|
||||
dim_class->name = "Motion Adaptive: Simple Detection";
|
||||
dim_class->nick = "greedyl";
|
||||
dim_class->latency = 1;
|
||||
|
||||
#ifdef HAVE_CPU_I386
|
||||
if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
|
||||
klass->scanline = deinterlace_greedy_packed422_scanline_mmxext;
|
||||
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
|
||||
klass->scanline = deinterlace_greedy_packed422_scanline_mmx;
|
||||
} else {
|
||||
klass->scanline = deinterlace_greedy_packed422_scanline_c;
|
||||
}
|
||||
#else
|
||||
klass->scanline = deinterlace_greedy_packed422_scanline_c;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_greedy_l_init (GstDeinterlaceMethodGreedyL * self)
|
||||
{
|
||||
self->max_comb = 15;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* GStreamer
|
||||
* Copyright (c) 2001 Tom Barry. All rights reserved.
|
||||
* 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
|
||||
|
@ -29,7 +30,7 @@
|
|||
#include "x86-64_macros.inc"
|
||||
|
||||
void
|
||||
FUNCT_NAME (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
||||
FUNCT_NAME (GstDeinterlaceMethodGreedyH *self, uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
||||
uint8_t * Dest, int size)
|
||||
{
|
||||
|
||||
|
@ -49,14 +50,14 @@ FUNCT_NAME (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
|||
int64_t LastAvg = 0; //interp value from left qword
|
||||
|
||||
// Set up our two parms that are actually evaluated for each pixel
|
||||
i = GreedyMaxComb;
|
||||
i = self->max_comb;
|
||||
MaxComb =
|
||||
i << 56 | i << 48 | i << 40 | i << 32 | i << 24 | i << 16 | i << 8 | i;
|
||||
|
||||
i = GreedyMotionThreshold; // scale to range of 0-257
|
||||
i = self->motion_threshold; // scale to range of 0-257
|
||||
MotionThreshold = i << 48 | i << 32 | i << 16 | i | UVMask;
|
||||
|
||||
i = GreedyMotionSense; // scale to range of 0-257
|
||||
i = self->motion_sense; // scale to range of 0-257
|
||||
MotionSense = i << 48 | i << 32 | i << 16 | i;
|
||||
|
||||
i = 0xffffffff - 256;
|
||||
|
@ -243,6 +244,6 @@ FUNCT_NAME (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
|||
|
||||
if (size % 8 != 0) {
|
||||
int offset = GST_ROUND_DOWN_8 (size);
|
||||
greedyDScaler_C (L1 + offset, L2 + offset, L3 + offset, L2P + offset, Dest + offset, size % 8);
|
||||
greedyDScaler_C (self, L1 + offset, L2 + offset, L3 + offset, L2P + offset, Dest + offset, size % 8);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* GStreamer
|
||||
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
|
||||
* 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
|
||||
|
@ -28,7 +29,6 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "greedyh.h"
|
||||
#include "greedyhmacros.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -39,13 +39,33 @@
|
|||
#include "plugins.h"
|
||||
#include "gstdeinterlace2.h"
|
||||
|
||||
static const unsigned int GreedyMaxComb = 5;
|
||||
static const unsigned int GreedyMotionThreshold = 25;
|
||||
static const unsigned int GreedyMotionSense = 30;
|
||||
#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ())
|
||||
#define GST_IS_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
|
||||
#define GST_IS_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
|
||||
#define GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass))
|
||||
#define GST_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyH))
|
||||
#define GST_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass))
|
||||
#define GST_DEINTERLACE_METHOD_GREEDY_H_CAST(obj) ((GstDeinterlaceMethodGreedyH*)(obj))
|
||||
|
||||
GType gst_deinterlace_method_greedy_h_get_type (void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstDeinterlaceMethod parent;
|
||||
|
||||
guint max_comb, motion_threshold, motion_sense;
|
||||
} GstDeinterlaceMethodGreedyH;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstDeinterlaceMethodClass parent_class;
|
||||
void (*scanline) (GstDeinterlaceMethodGreedyH * self, uint8_t * L2,
|
||||
uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size);
|
||||
} GstDeinterlaceMethodGreedyHClass;
|
||||
|
||||
void
|
||||
greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
||||
uint8_t * Dest, int size)
|
||||
greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2,
|
||||
uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size)
|
||||
{
|
||||
int Pos;
|
||||
uint8_t l1_l, l1_1_l, l3_l, l3_1_l;
|
||||
|
@ -60,6 +80,9 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
|||
uint8_t l2_l, l2_c, lp2_l, lp2_c;
|
||||
uint8_t l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff;
|
||||
uint8_t min_l, min_c, max_l, max_c;
|
||||
guint max_comb = self->max_comb;
|
||||
guint motion_sense = self->motion_sense;
|
||||
guint motion_threshold = self->motion_threshold;
|
||||
|
||||
for (Pos = 0; Pos < size; Pos += 2) {
|
||||
l1_l = L1[0];
|
||||
|
@ -130,26 +153,26 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
|||
max_l = MAX (l1_l, l3_l);
|
||||
min_l = MIN (l1_l, l3_l);
|
||||
|
||||
if (max_l < 256 - GreedyMaxComb)
|
||||
max_l += GreedyMaxComb;
|
||||
if (max_l < 256 - max_comb)
|
||||
max_l += max_comb;
|
||||
else
|
||||
max_l = 255;
|
||||
|
||||
if (min_l > GreedyMaxComb)
|
||||
min_l -= GreedyMaxComb;
|
||||
if (min_l > max_comb)
|
||||
min_l -= max_comb;
|
||||
else
|
||||
min_l = 0;
|
||||
|
||||
max_c = MAX (l1_c, l3_c);
|
||||
min_c = MIN (l1_c, l3_c);
|
||||
|
||||
if (max_c < 256 - GreedyMaxComb)
|
||||
max_c += GreedyMaxComb;
|
||||
if (max_c < 256 - max_comb)
|
||||
max_c += max_comb;
|
||||
else
|
||||
max_c = 255;
|
||||
|
||||
if (min_c > GreedyMaxComb)
|
||||
min_c -= GreedyMaxComb;
|
||||
if (min_c > max_comb)
|
||||
min_c -= max_comb;
|
||||
else
|
||||
min_c = 0;
|
||||
|
||||
|
@ -159,12 +182,12 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
|||
/* Do motion compensation for luma, i.e. how much
|
||||
* the weave pixel differs */
|
||||
mov_l = ABS (l2_l - lp2_l);
|
||||
if (mov_l > GreedyMotionThreshold)
|
||||
mov_l -= GreedyMotionThreshold;
|
||||
if (mov_l > motion_threshold)
|
||||
mov_l -= motion_threshold;
|
||||
else
|
||||
mov_l = 0;
|
||||
|
||||
mov_l = mov_l * GreedyMotionSense;
|
||||
mov_l = mov_l * motion_sense;
|
||||
if (mov_l > 256)
|
||||
mov_l = 256;
|
||||
|
||||
|
@ -211,11 +234,13 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
|||
#endif
|
||||
|
||||
static void
|
||||
deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
|
||||
deinterlace_frame_di_greedyh (GstDeinterlaceMethod * d_method,
|
||||
GstDeinterlace2 * object)
|
||||
{
|
||||
void (*func) (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
|
||||
uint8_t * Dest, int size);
|
||||
|
||||
GstDeinterlaceMethodGreedyH *self =
|
||||
GST_DEINTERLACE_METHOD_GREEDY_H (d_method);
|
||||
GstDeinterlaceMethodGreedyHClass *klass =
|
||||
GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
|
||||
int InfoIsOdd = 0;
|
||||
int Line;
|
||||
unsigned int Pitch = object->field_stride;
|
||||
|
@ -227,20 +252,6 @@ deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
|
|||
unsigned char *L2P; // ptr to prev Line2
|
||||
unsigned char *Dest = GST_BUFFER_DATA (object->out_buf);
|
||||
|
||||
#ifdef HAVE_CPU_I386
|
||||
if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMXEXT) {
|
||||
func = greedyDScaler_MMXEXT;
|
||||
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_3DNOW) {
|
||||
func = greedyDScaler_3DNOW;
|
||||
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
|
||||
func = greedyDScaler_MMX;
|
||||
} else {
|
||||
func = greedyDScaler_C;
|
||||
}
|
||||
#else
|
||||
func = greedyDScaler_C;
|
||||
#endif
|
||||
|
||||
// copy first even line no matter what, and the first odd line if we're
|
||||
// processing an EVEN field. (note diff from other deint rtns.)
|
||||
|
||||
|
@ -277,7 +288,7 @@ deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
|
|||
}
|
||||
|
||||
for (Line = 0; Line < (object->field_height - 1); ++Line) {
|
||||
func (L1, L2, L3, L2P, Dest, object->line_length);
|
||||
klass->scanline (self, L1, L2, L3, L2P, Dest, object->line_length);
|
||||
Dest += object->output_stride;
|
||||
memcpy (Dest, L3, object->line_length);
|
||||
Dest += object->output_stride;
|
||||
|
@ -293,31 +304,115 @@ deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
|
|||
}
|
||||
}
|
||||
|
||||
static deinterlace_method_t greedyh_method = {
|
||||
0, //DEINTERLACE_PLUGIN_API_VERSION,
|
||||
"Motion Adaptive: Advanced Detection",
|
||||
"AdaptiveAdvanced",
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
deinterlace_frame_di_greedyh,
|
||||
{"Uses heuristics to detect motion in the input",
|
||||
"frames and reconstruct image detail where",
|
||||
"possible. Use this for high quality output",
|
||||
"even on monitors set to an arbitrary refresh",
|
||||
"rate.",
|
||||
"",
|
||||
"Advanced detection uses linear interpolation",
|
||||
"where motion is detected, using a four-field",
|
||||
"buffer. This is the Greedy: High Motion",
|
||||
"deinterlacer from DScaler."}
|
||||
G_DEFINE_TYPE (GstDeinterlaceMethodGreedyH, gst_deinterlace_method_greedy_h,
|
||||
GST_TYPE_DEINTERLACE_METHOD);
|
||||
|
||||
enum
|
||||
{
|
||||
ARG_0,
|
||||
ARG_MAX_COMB,
|
||||
ARG_MOTION_THRESHOLD,
|
||||
ARG_MOTION_SENSE
|
||||
};
|
||||
|
||||
deinterlace_method_t *
|
||||
dscaler_greedyh_get_method (void)
|
||||
static void
|
||||
gst_deinterlace_method_greedy_h_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
return &greedyh_method;
|
||||
GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_MAX_COMB:
|
||||
self->max_comb = g_value_get_uint (value);
|
||||
break;
|
||||
case ARG_MOTION_THRESHOLD:
|
||||
self->motion_threshold = g_value_get_uint (value);
|
||||
break;
|
||||
case ARG_MOTION_SENSE:
|
||||
self->motion_sense = g_value_get_uint (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_greedy_h_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_MAX_COMB:
|
||||
g_value_set_uint (value, self->max_comb);
|
||||
break;
|
||||
case ARG_MOTION_THRESHOLD:
|
||||
g_value_set_uint (value, self->motion_threshold);
|
||||
break;
|
||||
case ARG_MOTION_SENSE:
|
||||
g_value_set_uint (value, self->motion_sense);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass *
|
||||
klass)
|
||||
{
|
||||
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
guint cpu_flags = oil_cpu_get_flags ();
|
||||
|
||||
gobject_class->set_property = gst_deinterlace_method_greedy_h_set_property;
|
||||
gobject_class->get_property = gst_deinterlace_method_greedy_h_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_MAX_COMB,
|
||||
g_param_spec_uint ("max-comb",
|
||||
"Max comb",
|
||||
"Max Comb", 0, 255, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||
);
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_MOTION_THRESHOLD,
|
||||
g_param_spec_uint ("motion-threshold",
|
||||
"Motion Threshold",
|
||||
"Motion Threshold",
|
||||
0, 255, 25, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||
);
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_MOTION_SENSE,
|
||||
g_param_spec_uint ("motion-sense",
|
||||
"Motion Sense",
|
||||
"Motion Sense",
|
||||
0, 255, 30, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||
);
|
||||
|
||||
dim_class->fields_required = 4;
|
||||
dim_class->deinterlace_frame = deinterlace_frame_di_greedyh;
|
||||
dim_class->name = "Motion Adaptive: Advanced Detection";
|
||||
dim_class->nick = "greedyh";
|
||||
dim_class->latency = 1;
|
||||
|
||||
#ifdef HAVE_CPU_I386
|
||||
if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
|
||||
klass->scanline = greedyDScaler_MMXEXT;
|
||||
} else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) {
|
||||
klass->scanline = greedyDScaler_3DNOW;
|
||||
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
|
||||
klass->scanline = greedyDScaler_MMX;
|
||||
} else {
|
||||
klass->scanline = greedyDScaler_C;
|
||||
}
|
||||
#else
|
||||
klass->scanline = greedyDScaler_C;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_greedy_h_init (GstDeinterlaceMethodGreedyH * self)
|
||||
{
|
||||
self->max_comb = 5;
|
||||
self->motion_threshold = 25;
|
||||
self->motion_sense = 30;
|
||||
}
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* GStreamer
|
||||
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Relicensed for GStreamer from GPL to LGPL with permit from Billy Biggs.
|
||||
* See: http://bugzilla.gnome.org/show_bug.cgi?id=163578
|
||||
*/
|
||||
|
||||
#ifndef GREEDYH_H_INCLUDED
|
||||
#define GREEDYH_H_INCLUDED
|
||||
|
||||
#include "gstdeinterlace2.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void greedyh_init( void );
|
||||
void greedyh_filter_mmx( GstDeinterlace2 *object );
|
||||
void greedyh_filter_3dnow( GstDeinterlace2 *object );
|
||||
void greedyh_filter_sse( GstDeinterlace2 *object );
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* GREEDYH_H_INCLUDED */
|
|
@ -2,6 +2,7 @@
|
|||
*
|
||||
* GStreamer
|
||||
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
|
||||
* 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
|
||||
|
@ -27,10 +28,15 @@
|
|||
#ifndef TVTIME_PLUGINS_H_INCLUDED
|
||||
#define TVTIME_PLUGINS_H_INCLUDED
|
||||
|
||||
deinterlace_method_t* dscaler_tomsmocomp_get_method( void );
|
||||
deinterlace_method_t* dscaler_greedyh_get_method( void );
|
||||
deinterlace_method_t* dscaler_greedyl_get_method( void );
|
||||
deinterlace_method_t* dscaler_vfir_get_method( void );
|
||||
#define GST_TYPE_DEINTERLACE_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ())
|
||||
#define GST_TYPE_DEINTERLACE_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ())
|
||||
#define GST_TYPE_DEINTERLACE_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ())
|
||||
#define GST_TYPE_DEINTERLACE_VFIR (gst_deinterlace_method_vfir_get_type ())
|
||||
|
||||
GType gst_deinterlace_method_tomsmocomp_get_type (void);
|
||||
GType gst_deinterlace_method_greedy_h_get_type (void);
|
||||
GType gst_deinterlace_method_greedy_l_get_type (void);
|
||||
GType gst_deinterlace_method_vfir_get_type (void);
|
||||
|
||||
//void linear_plugin_init( void );
|
||||
//void scalerbob_plugin_init( void );
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/**
|
||||
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
|
||||
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -31,22 +32,28 @@
|
|||
#include "tomsmocomp/tomsmocompmacros.h"
|
||||
#include "x86-64_macros.inc"
|
||||
|
||||
#define SearchEffortDefault 5
|
||||
#define UseStrangeBobDefault 0
|
||||
#define GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ())
|
||||
#define GST_IS_DEINTERLACE_METHOD_TOMSMOCOMP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP))
|
||||
#define GST_IS_DEINTERLACE_METHOD_TOMSMOCOMP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP))
|
||||
#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoCompClass))
|
||||
#define GST_DEINTERLACE_METHOD_TOMSMOCOMP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoComp))
|
||||
#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoCompClass))
|
||||
#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_CAST(obj) ((GstDeinterlaceMethodTomsMoComp*)(obj))
|
||||
|
||||
static long SearchEffort;
|
||||
static int UseStrangeBob;
|
||||
static int IsOdd;
|
||||
static const unsigned char *pWeaveSrc;
|
||||
static const unsigned char *pWeaveSrcP;
|
||||
static unsigned char *pWeaveDest;
|
||||
static const unsigned char *pCopySrc;
|
||||
static const unsigned char *pCopySrcP;
|
||||
static unsigned char *pCopyDest;
|
||||
static int src_pitch;
|
||||
static int dst_pitch;
|
||||
static int rowsize;
|
||||
static int FldHeight;
|
||||
GType gst_deinterlace_method_tomsmocomp_get_type (void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstDeinterlaceMethod parent;
|
||||
|
||||
guint search_effort;
|
||||
gboolean strange_bob;
|
||||
} GstDeinterlaceMethodTomsMoComp;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstDeinterlaceMethodClass parent_class;
|
||||
} GstDeinterlaceMethodTomsMoCompClass;
|
||||
|
||||
static int
|
||||
Fieldcopy (void *dest, const void *src, size_t count,
|
||||
|
@ -90,71 +97,96 @@ Fieldcopy (void *dest, const void *src, size_t count,
|
|||
#undef SSE_TYPE
|
||||
#undef FUNCT_NAME
|
||||
|
||||
static void
|
||||
tomsmocomp_init (void)
|
||||
G_DEFINE_TYPE (GstDeinterlaceMethodTomsMoComp,
|
||||
gst_deinterlace_method_tomsmocomp, GST_TYPE_DEINTERLACE_METHOD);
|
||||
|
||||
enum
|
||||
{
|
||||
SearchEffort = SearchEffortDefault;
|
||||
UseStrangeBob = UseStrangeBobDefault;
|
||||
}
|
||||
ARG_0,
|
||||
ARG_SEARCH_EFFORT,
|
||||
ARG_STRANGE_BOB
|
||||
};
|
||||
|
||||
static void
|
||||
tomsmocomp_filter_mmx (GstDeinterlace2 * object)
|
||||
gst_deinterlace_method_tomsmocomp_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
tomsmocompDScaler_MMX (object);
|
||||
}
|
||||
GstDeinterlaceMethodTomsMoComp *self =
|
||||
GST_DEINTERLACE_METHOD_TOMSMOCOMP (object);
|
||||
|
||||
static void
|
||||
tomsmocomp_filter_3dnow (GstDeinterlace2 * object)
|
||||
{
|
||||
tomsmocompDScaler_3DNOW (object);
|
||||
}
|
||||
|
||||
static void
|
||||
tomsmocomp_filter_sse (GstDeinterlace2 * object)
|
||||
{
|
||||
tomsmocompDScaler_SSE (object);
|
||||
}
|
||||
|
||||
static void
|
||||
deinterlace_frame_di_tomsmocomp (GstDeinterlace2 * object)
|
||||
{
|
||||
if (object->cpu_feature_flags & OIL_IMPL_FLAG_SSE) {
|
||||
tomsmocomp_filter_sse (object);
|
||||
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_3DNOW) {
|
||||
tomsmocomp_filter_3dnow (object);
|
||||
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
|
||||
tomsmocomp_filter_mmx (object);
|
||||
} else {
|
||||
g_assert_not_reached ();
|
||||
switch (prop_id) {
|
||||
case ARG_SEARCH_EFFORT:
|
||||
self->search_effort = g_value_get_uint (value);
|
||||
break;
|
||||
case ARG_STRANGE_BOB:
|
||||
self->strange_bob = g_value_get_boolean (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static deinterlace_method_t tomsmocompmethod = {
|
||||
0, //DEINTERLACE_PLUGIN_API_VERSION,
|
||||
"Motion Adaptive: Motion Search",
|
||||
"AdaptiveSearch",
|
||||
4,
|
||||
OIL_IMPL_FLAG_MMX,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
deinterlace_frame_di_tomsmocomp,
|
||||
{"Uses heuristics to detect motion in the input",
|
||||
"frames and reconstruct image detail where",
|
||||
"possible. Use this for high quality output",
|
||||
"even on monitors set to an arbitrary refresh",
|
||||
"rate.",
|
||||
"",
|
||||
"Motion search mode finds and follows motion",
|
||||
"vectors for accurate interpolation. This is",
|
||||
"the TomsMoComp deinterlacer from DScaler.",
|
||||
""}
|
||||
};
|
||||
|
||||
deinterlace_method_t *
|
||||
dscaler_tomsmocomp_get_method (void)
|
||||
static void
|
||||
gst_deinterlace_method_tomsmocomp_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
tomsmocomp_init ();
|
||||
return &tomsmocompmethod;
|
||||
GstDeinterlaceMethodTomsMoComp *self =
|
||||
GST_DEINTERLACE_METHOD_TOMSMOCOMP (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_SEARCH_EFFORT:
|
||||
g_value_set_uint (value, self->search_effort);
|
||||
break;
|
||||
case ARG_STRANGE_BOB:
|
||||
g_value_set_boolean (value, self->strange_bob);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_tomsmocomp_class_init
|
||||
(GstDeinterlaceMethodTomsMoCompClass * klass)
|
||||
{
|
||||
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
guint cpu_flags = oil_cpu_get_flags ();
|
||||
|
||||
gobject_class->set_property = gst_deinterlace_method_tomsmocomp_set_property;
|
||||
gobject_class->get_property = gst_deinterlace_method_tomsmocomp_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_SEARCH_EFFORT,
|
||||
g_param_spec_uint ("search-effort",
|
||||
"Search Effort",
|
||||
"Search Effort", 0, 27, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||
);
|
||||
|
||||
g_object_class_install_property (gobject_class, ARG_STRANGE_BOB,
|
||||
g_param_spec_boolean ("strange-bob",
|
||||
"Strange Bob",
|
||||
"Use strange bob", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
|
||||
);
|
||||
|
||||
dim_class->fields_required = 4;
|
||||
dim_class->name = "Motion Adaptive: Motion Search";
|
||||
dim_class->nick = "tomsmocomp";
|
||||
dim_class->latency = 1;
|
||||
|
||||
if (cpu_flags & OIL_IMPL_FLAG_SSE) {
|
||||
dim_class->deinterlace_frame = tomsmocompDScaler_SSE;
|
||||
} else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) {
|
||||
dim_class->deinterlace_frame = tomsmocompDScaler_3DNOW;
|
||||
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
|
||||
dim_class->deinterlace_frame = tomsmocompDScaler_MMX;
|
||||
} else {
|
||||
dim_class->available = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_tomsmocomp_init (GstDeinterlaceMethodTomsMoComp * self)
|
||||
{
|
||||
self->search_effort = 5;
|
||||
self->strange_bob = FALSE;
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef TOMSMOCOMP_H_INCLUDED
|
||||
#define TOMSMOCOMP_H_INCLUDED
|
||||
|
||||
#include "gstdeinterlace2.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int Search_Effort_0();
|
||||
int Search_Effort_1();
|
||||
int Search_Effort_3();
|
||||
int Search_Effort_5();
|
||||
int Search_Effort_9();
|
||||
int Search_Effort_11();
|
||||
int Search_Effort_13();
|
||||
int Search_Effort_15();
|
||||
int Search_Effort_19();
|
||||
int Search_Effort_21();
|
||||
int Search_Effort_Max();
|
||||
|
||||
int Search_Effort_0_SB();
|
||||
int Search_Effort_1_SB();
|
||||
int Search_Effort_3_SB();
|
||||
int Search_Effort_5_SB();
|
||||
int Search_Effort_9_SB();
|
||||
int Search_Effort_11_SB();
|
||||
int Search_Effort_13_SB();
|
||||
int Search_Effort_15_SB();
|
||||
int Search_Effort_19_SB();
|
||||
int Search_Effort_21_SB();
|
||||
int Search_Effort_Max_SB();
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* TOMSMOCOMP_H_INCLUDED */
|
|
@ -33,11 +33,11 @@
|
|||
#endif
|
||||
|
||||
#if defined(IS_SSE)
|
||||
#define SEFUNC(x) Search_Effort_SSE_##x()
|
||||
#define SEFUNC(x) Search_Effort_SSE_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight)
|
||||
#elif defined(IS_3DNOW)
|
||||
#define SEFUNC(x) Search_Effort_3DNOW_##x()
|
||||
#define SEFUNC(x) Search_Effort_3DNOW_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight)
|
||||
#else
|
||||
#define SEFUNC(x) Search_Effort_MMX_##x()
|
||||
#define SEFUNC(x) Search_Effort_MMX_##x(int src_pitch, int dst_pitch, int rowsize, const unsigned char *pWeaveSrc, const unsigned char *pWeaveSrcP, unsigned char *pWeaveDest, int IsOdd, const unsigned char *pCopySrc, const unsigned char *pCopySrcP, int FldHeight)
|
||||
#endif
|
||||
|
||||
#include "TomsMoCompAll2.inc"
|
||||
|
@ -48,9 +48,32 @@
|
|||
|
||||
#undef USE_STRANGE_BOB
|
||||
|
||||
#undef SEFUNC
|
||||
#if defined(IS_SSE)
|
||||
#define SEFUNC(x) Search_Effort_SSE_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight)
|
||||
#elif defined(IS_3DNOW)
|
||||
#define SEFUNC(x) Search_Effort_3DNOW_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight)
|
||||
#else
|
||||
#define SEFUNC(x) Search_Effort_MMX_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight)
|
||||
#endif
|
||||
|
||||
void FUNCT_NAME(GstDeinterlace2* object)
|
||||
void FUNCT_NAME(GstDeinterlaceMethod *d_method, GstDeinterlace2* object)
|
||||
{
|
||||
GstDeinterlaceMethodTomsMoComp *self = GST_DEINTERLACE_METHOD_TOMSMOCOMP (d_method);
|
||||
long SearchEffort = self->search_effort;
|
||||
int UseStrangeBob = self->strange_bob;
|
||||
int IsOdd;
|
||||
const unsigned char *pWeaveSrc;
|
||||
const unsigned char *pWeaveSrcP;
|
||||
unsigned char *pWeaveDest;
|
||||
const unsigned char *pCopySrc;
|
||||
const unsigned char *pCopySrcP;
|
||||
unsigned char *pCopyDest;
|
||||
int src_pitch;
|
||||
int dst_pitch;
|
||||
int rowsize;
|
||||
int FldHeight;
|
||||
|
||||
/* double stride do address just every odd/even scanline */
|
||||
src_pitch = object->field_stride;
|
||||
dst_pitch = object->output_stride;
|
||||
|
@ -80,10 +103,6 @@ void FUNCT_NAME(GstDeinterlace2* object)
|
|||
}
|
||||
|
||||
|
||||
#ifdef IS_SSE2
|
||||
// SSE2 support temporarily deleted
|
||||
#endif
|
||||
|
||||
// copy 1st and last weave lines
|
||||
Fieldcopy(pWeaveDest, pCopySrc, rowsize,
|
||||
1, dst_pitch*2, src_pitch);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* GStreamer
|
||||
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
|
||||
* Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
|
||||
* 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
|
||||
|
@ -36,6 +37,26 @@
|
|||
#include "gstdeinterlace2.h"
|
||||
#include <string.h>
|
||||
|
||||
#define GST_TYPE_DEINTERLACE_METHOD_VFIR (gst_deinterlace_method_vfir_get_type ())
|
||||
#define GST_IS_DEINTERLACE_METHOD_VFIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR))
|
||||
#define GST_IS_DEINTERLACE_METHOD_VFIR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_VFIR))
|
||||
#define GST_DEINTERLACE_METHOD_VFIR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIRClass))
|
||||
#define GST_DEINTERLACE_METHOD_VFIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIR))
|
||||
#define GST_DEINTERLACE_METHOD_VFIR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIRClass))
|
||||
#define GST_DEINTERLACE_METHOD_VFIR_CAST(obj) ((GstDeinterlaceMethodVFIR*)(obj))
|
||||
|
||||
GType gst_deinterlace_method_vfir_get_type (void);
|
||||
|
||||
typedef GstDeinterlaceMethod GstDeinterlaceMethodVFIR;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstDeinterlaceMethodClass parent_class;
|
||||
void (*scanline) (uint8_t * dst, uint8_t * lum_m4,
|
||||
uint8_t * lum_m3, uint8_t * lum_m2,
|
||||
uint8_t * lum_m1, uint8_t * lum, int size);
|
||||
} GstDeinterlaceMethodVFIRClass;
|
||||
|
||||
/*
|
||||
* The MPEG2 spec uses a slightly harsher filter, they specify
|
||||
* [-1 8 2 8 -1]. ffmpeg uses a similar filter but with more of
|
||||
|
@ -122,25 +143,15 @@ deinterlace_line_mmx (uint8_t * dst, uint8_t * lum_m4,
|
|||
#endif
|
||||
|
||||
static void
|
||||
deinterlace_frame_vfir (GstDeinterlace2 * object)
|
||||
deinterlace_frame_vfir (GstDeinterlaceMethod * d_method,
|
||||
GstDeinterlace2 * object)
|
||||
{
|
||||
void (*func) (uint8_t * dst, uint8_t * lum_m4,
|
||||
uint8_t * lum_m3, uint8_t * lum_m2,
|
||||
uint8_t * lum_m1, uint8_t * lum, int size);
|
||||
GstDeinterlaceMethodVFIRClass *klass =
|
||||
GST_DEINTERLACE_METHOD_VFIR_GET_CLASS (d_method);
|
||||
gint line = 0;
|
||||
uint8_t *cur_field, *last_field;
|
||||
uint8_t *t0, *b0, *tt1, *m1, *bb1, *out_data;
|
||||
|
||||
#ifdef HAVE_CPU_I386
|
||||
if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
|
||||
func = deinterlace_line_mmx;
|
||||
} else {
|
||||
func = deinterlace_line_c;
|
||||
}
|
||||
#else
|
||||
func = deinterlace_line_c;
|
||||
#endif
|
||||
|
||||
cur_field =
|
||||
GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
|
||||
last_field =
|
||||
|
@ -173,7 +184,7 @@ deinterlace_frame_vfir (GstDeinterlace2 * object)
|
|||
bb1 = tt1;
|
||||
}
|
||||
|
||||
func (out_data, tt1, t0, m1, b0, bb1, object->line_length);
|
||||
klass->scanline (out_data, tt1, t0, m1, b0, bb1, object->line_length);
|
||||
out_data += object->output_stride;
|
||||
cur_field += object->field_stride;
|
||||
last_field += object->field_stride;
|
||||
|
@ -189,31 +200,33 @@ deinterlace_frame_vfir (GstDeinterlace2 * object)
|
|||
}
|
||||
}
|
||||
|
||||
static deinterlace_method_t vfirmethod = {
|
||||
0, //DEINTERLACE_PLUGIN_API_VERSION,
|
||||
"Blur: Vertical",
|
||||
"BlurVertical",
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
deinterlace_frame_vfir,
|
||||
{"Avoids flicker by blurring consecutive frames",
|
||||
"of input. Use this if you want to run your",
|
||||
"monitor at an arbitrary refresh rate and not",
|
||||
"use much CPU, and are willing to sacrifice",
|
||||
"detail.",
|
||||
"",
|
||||
"Vertical mode blurs favouring the most recent",
|
||||
"field for less visible trails. From the",
|
||||
"deinterlacer filter in ffmpeg.",
|
||||
""}
|
||||
};
|
||||
G_DEFINE_TYPE (GstDeinterlaceMethodVFIR, gst_deinterlace_method_vfir,
|
||||
GST_TYPE_DEINTERLACE_METHOD);
|
||||
|
||||
deinterlace_method_t *
|
||||
dscaler_vfir_get_method (void)
|
||||
static void
|
||||
gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass)
|
||||
{
|
||||
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
|
||||
guint cpu_flags = oil_cpu_get_flags ();
|
||||
|
||||
dim_class->fields_required = 2;
|
||||
dim_class->deinterlace_frame = deinterlace_frame_vfir;
|
||||
dim_class->name = "Blur Vertical";
|
||||
dim_class->nick = "vfir";
|
||||
dim_class->latency = 0;
|
||||
|
||||
#ifdef HAVE_CPU_I386
|
||||
if (cpu_flags & OIL_IMPL_FLAG_MMX) {
|
||||
klass->scanline = deinterlace_line_mmx;
|
||||
} else {
|
||||
klass->scanline = deinterlace_line_c;
|
||||
}
|
||||
#else
|
||||
klass->scanline = deinterlace_line_c;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gst_deinterlace_method_vfir_init (GstDeinterlaceMethodVFIR * self)
|
||||
{
|
||||
return &vfirmethod;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue