[MOVED FROM BAD 23/56] 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:
Sebastian Dröge 2008-07-05 16:47:32 +00:00 committed by Sebastian Dröge
parent e5231e5641
commit fb7f06ad04
12 changed files with 708 additions and 469 deletions

View file

@ -17,7 +17,6 @@ noinst_HEADERS = \
gstdeinterlace2.h \ gstdeinterlace2.h \
tvtime/mmx.h \ tvtime/mmx.h \
tvtime/sse.h \ tvtime/sse.h \
tvtime/greedyh.h \
tvtime/greedyh.asm \ tvtime/greedyh.asm \
tvtime/greedyhmacros.h \ tvtime/greedyhmacros.h \
tvtime/plugins.h \ tvtime/plugins.h \

View file

@ -1,7 +1,7 @@
/* /*
* GStreamer * GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -49,25 +49,56 @@ enum
ARG_FIELD_LAYOUT ARG_FIELD_LAYOUT
}; };
#define GST_TYPE_DEINTERLACE2_METHOD (gst_deinterlace2_method_get_type ()) G_DEFINE_TYPE (GstDeinterlaceMethod, gst_deinterlace_method, GST_TYPE_OBJECT);
static GType
gst_deinterlace2_method_get_type (void)
{
static GType deinterlace2_method_type = 0;
static const GEnumValue method_types[] = { static void
{GST_DEINTERLACE2_TOM, "Toms Motion Compensation", "tomsmc"}, 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_H, "Greedy High Motion", "greedyh"},
{GST_DEINTERLACE2_GREEDY_L, "Greedy Low Motion", "greedyl"}, {GST_DEINTERLACE2_GREEDY_L, "Greedy Low Motion", "greedyl"},
{GST_DEINTERLACE2_VFIR, "Vertical Blur", "vfir"}, {GST_DEINTERLACE2_VFIR, "Vertical Blur", "vfir"},
{0, NULL, NULL}, {0, NULL, NULL},
}; };
if (!deinterlace2_method_type) { if (!deinterlace2_methods_type) {
deinterlace2_method_type = deinterlace2_methods_type =
g_enum_register_static ("GstDeinterlace2Methods", method_types); 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 ()) #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); static void gst_deinterlace2_reset (GstDeinterlace2 * object);
GST_BOILERPLATE (GstDeinterlace2, gst_deinterlace2, GstElement, static void gst_deinterlace2_child_proxy_interface_init (gpointer g_iface,
GST_TYPE_ELEMENT); 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 static void
gst_deinterlace2_base_init (gpointer klass) gst_deinterlace2_base_init (gpointer klass)
@ -177,8 +266,9 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
g_param_spec_enum ("method", g_param_spec_enum ("method",
"Method", "Method",
"Deinterlace Method", "Deinterlace Method",
GST_TYPE_DEINTERLACE2_METHOD, GST_TYPE_DEINTERLACE2_METHODS,
GST_DEINTERLACE2_TOM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS) GST_DEINTERLACE2_TOMSMOCOMP,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
); );
g_object_class_install_property (gobject_class, ARG_FIELDS, 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); 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 static void
gst_deinterlace2_init (GstDeinterlace2 * object, GstDeinterlace2Class * klass) 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)); gst_element_no_more_pads (GST_ELEMENT (object));
object->cpu_feature_flags = oil_cpu_get_flags (); gst_deinterlace2_set_method (object, GST_DEINTERLACE2_TOMSMOCOMP);
object->method = dscaler_tomsmocomp_get_method ();
object->field_layout = GST_DEINTERLACE2_LAYOUT_AUTO; object->field_layout = GST_DEINTERLACE2_LAYOUT_AUTO;
object->fields = GST_DEINTERLACE2_ALL; object->fields = GST_DEINTERLACE2_ALL;
@ -275,37 +390,6 @@ gst_deinterlace2_reset (GstDeinterlace2 * object)
gst_deinterlace2_reset_history (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 static void
gst_deinterlace2_set_property (GObject * _object, guint prop_id, gst_deinterlace2_set_property (GObject * _object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
@ -367,7 +451,14 @@ gst_deinterlace2_get_property (GObject * _object, guint prop_id,
static void static void
gst_deinterlace2_finalize (GObject * object) 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); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -456,6 +547,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
GstDeinterlace2 *object = NULL; GstDeinterlace2 *object = NULL;
GstClockTime timestamp; GstClockTime timestamp;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
gint fields_required = 0;
object = GST_DEINTERLACE2 (GST_PAD_PARENT (pad)); object = GST_DEINTERLACE2 (GST_PAD_PARENT (pad));
@ -464,9 +556,11 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
if (object->method != NULL) { if (object->method != NULL) {
int cur_field_idx = 0; int cur_field_idx = 0;
fields_required =
gst_deinterlace_method_get_fields_required (object->method);
/* Not enough fields in the history */ /* 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 */ /* TODO: do bob or just forward frame */
GST_DEBUG ("HistoryCount=%d", object->history_count); GST_DEBUG ("HistoryCount=%d", object->history_count);
return GST_FLOW_OK; return GST_FLOW_OK;
@ -479,7 +573,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
if (object->fields == GST_DEINTERLACE2_BF) if (object->fields == GST_DEINTERLACE2_BF)
GST_DEBUG ("Bottom fields"); 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 if ((object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP
&& object->fields == GST_DEINTERLACE2_TF) || && object->fields == GST_DEINTERLACE2_TF) ||
@ -494,25 +588,23 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
return ret; return ret;
/* do magic calculus */ /* do magic calculus */
if (object->method->deinterlace_frame != NULL) { gst_deinterlace_method_deinterlace_frame (object->method, object);
object->method->deinterlace_frame (object);
buf = gst_deinterlace2_pop_history (object); buf = gst_deinterlace2_pop_history (object);
timestamp = GST_BUFFER_TIMESTAMP (buf); timestamp = GST_BUFFER_TIMESTAMP (buf);
gst_buffer_unref (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_BUFFER_DURATION (object->out_buf) =
GST_SECOND / object->frame_rate_d / object->frame_rate_n; GST_BUFFER_DURATION (object->out_buf) / 2;
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); ret = gst_pad_push (object->srcpad, object->out_buf);
object->out_buf = NULL; object->out_buf = NULL;
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
return ret; return ret;
}
} }
/* no calculation done: remove excess field */ /* no calculation done: remove excess field */
else if (object->field_history[cur_field_idx].flags == else if (object->field_history[cur_field_idx].flags ==
@ -522,7 +614,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
gst_buffer_unref (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 */ /* deinterlace bottom_field */
if ((object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM if ((object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM
@ -538,26 +630,24 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
return ret; return ret;
/* do magic calculus */ /* do magic calculus */
if (object->method->deinterlace_frame != NULL) { gst_deinterlace_method_deinterlace_frame (object->method, object);
object->method->deinterlace_frame (object);
buf = gst_deinterlace2_pop_history (object); buf = gst_deinterlace2_pop_history (object);
timestamp = GST_BUFFER_TIMESTAMP (buf); timestamp = GST_BUFFER_TIMESTAMP (buf);
gst_buffer_unref (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_BUFFER_DURATION (object->out_buf) =
GST_SECOND / object->frame_rate_d / object->frame_rate_n; GST_BUFFER_DURATION (object->out_buf) / 2;
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); ret = gst_pad_push (object->srcpad, object->out_buf);
object->out_buf = NULL; object->out_buf = NULL;
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
return ret; return ret;
}
} }
/* no calculation done: remove excess field */ /* no calculation done: remove excess field */
else if (object->field_history[cur_field_idx].flags == 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 ((peer = gst_pad_get_peer (object->sinkpad))) {
if ((res = gst_pad_query (peer, query))) { if ((res = gst_pad_query (peer, query))) {
GstClockTime latency; 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); gst_query_parse_latency (query, &live, &min, &max);
@ -766,7 +861,7 @@ gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
/* add our own latency */ /* add our own latency */
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); GST_SECOND, object->frame_rate_d, object->frame_rate_n);
latency /= 2; latency /= 2;

View file

@ -1,7 +1,7 @@
/* /*
* GStreamer * GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -45,29 +45,40 @@ G_BEGIN_DECLS
typedef struct _GstDeinterlace2 GstDeinterlace2; typedef struct _GstDeinterlace2 GstDeinterlace2;
typedef struct _GstDeinterlace2Class GstDeinterlace2Class; typedef struct _GstDeinterlace2Class GstDeinterlace2Class;
typedef struct deinterlace_setting_s deinterlace_setting_t; #define GST_TYPE_DEINTERLACE_METHOD (gst_deinterlace_method_get_type ())
typedef struct deinterlace_method_s deinterlace_method_t; #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. * This structure defines the deinterlacer plugin.
*/ */
struct deinterlace_method_s
{ struct _GstDeinterlaceMethod {
int version; GstObject parent;
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 _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 MAX_FIELD_HISTORY 10
#define PICTURE_PROGRESSIVE 0 #define PICTURE_PROGRESSIVE 0
@ -75,8 +86,6 @@ struct deinterlace_method_s
#define PICTURE_INTERLACED_TOP 2 #define PICTURE_INTERLACED_TOP 2
#define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP) #define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP)
typedef void (MEMCPY_FUNC) (void *pOutput, const void *pInput, size_t nSize);
typedef struct typedef struct
{ {
/* pointer to the start of data for this field */ /* pointer to the start of data for this field */
@ -87,7 +96,7 @@ typedef struct
typedef enum typedef enum
{ {
GST_DEINTERLACE2_TOM, GST_DEINTERLACE2_TOMSMOCOMP,
GST_DEINTERLACE2_GREEDY_H, GST_DEINTERLACE2_GREEDY_H,
GST_DEINTERLACE2_GREEDY_L, GST_DEINTERLACE2_GREEDY_L,
GST_DEINTERLACE2_VFIR GST_DEINTERLACE2_VFIR
@ -115,7 +124,6 @@ struct _GstDeinterlace2
guint history_count; guint history_count;
guint cpu_feature_flags;
GstDeinterlace2FieldLayout field_layout; GstDeinterlace2FieldLayout field_layout;
guint frame_size; guint frame_size;
@ -124,7 +132,7 @@ struct _GstDeinterlace2
GstDeinterlace2Fields fields; GstDeinterlace2Fields fields;
GstDeinterlace2Methods method_id; GstDeinterlace2Methods method_id;
deinterlace_method_t *method; GstDeinterlaceMethod *method;
/* The most recent pictures /* The most recent pictures
PictureHistory[0] is always the most recent. PictureHistory[0] is always the most recent.

View file

@ -4,6 +4,8 @@
* Copyright (c) 2000 Tom Barry All rights reserved. * Copyright (c) 2000 Tom Barry All rights reserved.
* mmx.h port copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either * License as published by the Free Software Foundation; either
@ -35,6 +37,30 @@
#include "gstdeinterlace2.h" #include "gstdeinterlace2.h"
#include <string.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 // This is a simple lightweight DeInterlace method that uses little CPU time
// but gives very good results for low or intermedite motion. // but gives very good results for low or intermedite motion.
// It defers frames by one field, but that does not seem to produce noticeable // 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 // 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. // Blended Clip but this give too good results for the CPU to ignore here.
static const int GreedyMaxComb = 15;
static inline void 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) uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{ {
int avg, l2_diff, lp2_diff, max, min, best; int avg, l2_diff, lp2_diff, max, min, best;
guint max_comb = self->max_comb;
// L2 == m0 // L2 == m0
// L1 == t1 // L1 == t1
@ -74,13 +100,13 @@ deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
max = MAX (*t1, *b1); max = MAX (*t1, *b1);
min = MIN (*t1, *b1); min = MIN (*t1, *b1);
if (max < 256 - GreedyMaxComb) if (max < 256 - max_comb)
max += GreedyMaxComb; max += max_comb;
else else
max = 255; max = 255;
if (min > GreedyMaxComb) if (min > max_comb)
min -= GreedyMaxComb; min -= max_comb;
else else
min = 0; min = 0;
@ -98,22 +124,22 @@ deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
#ifdef HAVE_CPU_I386 #ifdef HAVE_CPU_I386
#include "mmx.h" #include "mmx.h"
static void 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) uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{ {
mmx_t MaxComb; mmx_t MaxComb;
mmx_t ShiftMask; mmx_t ShiftMask;
// How badly do we let it weave? 0-255 // How badly do we let it weave? 0-255
MaxComb.ub[0] = GreedyMaxComb; MaxComb.ub[0] = self->max_comb;
MaxComb.ub[1] = GreedyMaxComb; MaxComb.ub[1] = self->max_comb;
MaxComb.ub[2] = GreedyMaxComb; MaxComb.ub[2] = self->max_comb;
MaxComb.ub[3] = GreedyMaxComb; MaxComb.ub[3] = self->max_comb;
MaxComb.ub[4] = GreedyMaxComb; MaxComb.ub[4] = self->max_comb;
MaxComb.ub[5] = GreedyMaxComb; MaxComb.ub[5] = self->max_comb;
MaxComb.ub[6] = GreedyMaxComb; MaxComb.ub[6] = self->max_comb;
MaxComb.ub[7] = GreedyMaxComb; MaxComb.ub[7] = self->max_comb;
ShiftMask.ub[0] = 0x7f; ShiftMask.ub[0] = 0x7f;
ShiftMask.ub[1] = 0x7f; ShiftMask.ub[1] = 0x7f;
@ -207,26 +233,28 @@ deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
} }
emms (); emms ();
if (width > 0) 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" #include "sse.h"
static void static void
deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1, deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlaceMethodGreedyL *
uint8_t * b1, uint8_t * m2, uint8_t * output, int width) self, uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2,
uint8_t * output, int width)
{ {
mmx_t MaxComb; mmx_t MaxComb;
// How badly do we let it weave? 0-255 // How badly do we let it weave? 0-255
MaxComb.ub[0] = GreedyMaxComb; MaxComb.ub[0] = self->max_comb;
MaxComb.ub[1] = GreedyMaxComb; MaxComb.ub[1] = self->max_comb;
MaxComb.ub[2] = GreedyMaxComb; MaxComb.ub[2] = self->max_comb;
MaxComb.ub[3] = GreedyMaxComb; MaxComb.ub[3] = self->max_comb;
MaxComb.ub[4] = GreedyMaxComb; MaxComb.ub[4] = self->max_comb;
MaxComb.ub[5] = GreedyMaxComb; MaxComb.ub[5] = self->max_comb;
MaxComb.ub[6] = GreedyMaxComb; MaxComb.ub[6] = self->max_comb;
MaxComb.ub[7] = GreedyMaxComb; MaxComb.ub[7] = self->max_comb;
// L2 == m0 // L2 == m0
// L1 == t1 // L1 == t1
@ -299,17 +327,20 @@ deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1,
emms (); emms ();
if (width > 0) 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 #endif
static void 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, GstDeinterlaceMethodGreedyL *self =
uint8_t * Dest, int size); GST_DEINTERLACE_METHOD_GREEDY_L (d_method);
GstDeinterlaceMethodGreedyLClass *klass =
GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS (self);
int InfoIsOdd = 0; int InfoIsOdd = 0;
int Line; int Line;
unsigned int Pitch = object->field_stride; 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 *L2P; // ptr to prev Line2
unsigned char *Dest = GST_BUFFER_DATA (object->out_buf); 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 // 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.) // 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) { 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; Dest += object->output_stride;
memcpy (Dest, L3, object->line_length); memcpy (Dest, L3, object->line_length);
Dest += object->output_stride; 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, G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l,
"Motion Adaptive: Simple Detection", GST_TYPE_DEINTERLACE_METHOD);
"AdaptiveSimple",
4, enum
0, {
0, ARG_0,
0, ARG_MAX_COMB
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."}
}; };
deinterlace_method_t * static void
dscaler_greedyl_get_method (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;
} }

View file

@ -2,6 +2,7 @@
* *
* GStreamer * GStreamer
* Copyright (c) 2001 Tom Barry. All rights reserved. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -29,7 +30,7 @@
#include "x86-64_macros.inc" #include "x86-64_macros.inc"
void 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) 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 int64_t LastAvg = 0; //interp value from left qword
// Set up our two parms that are actually evaluated for each pixel // Set up our two parms that are actually evaluated for each pixel
i = GreedyMaxComb; i = self->max_comb;
MaxComb = MaxComb =
i << 56 | i << 48 | i << 40 | i << 32 | i << 24 | i << 16 | i << 8 | i; 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; 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; MotionSense = i << 48 | i << 32 | i << 16 | i;
i = 0xffffffff - 256; 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) { if (size % 8 != 0) {
int offset = GST_ROUND_DOWN_8 (size); 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);
} }
} }

View file

@ -2,6 +2,7 @@
* *
* GStreamer * GStreamer
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -28,7 +29,6 @@
# include "config.h" # include "config.h"
#endif #endif
#include "greedyh.h"
#include "greedyhmacros.h" #include "greedyhmacros.h"
#include <stdlib.h> #include <stdlib.h>
@ -39,13 +39,33 @@
#include "plugins.h" #include "plugins.h"
#include "gstdeinterlace2.h" #include "gstdeinterlace2.h"
static const unsigned int GreedyMaxComb = 5; #define GST_TYPE_DEINTERLACE_METHOD_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ())
static const unsigned int GreedyMotionThreshold = 25; #define GST_IS_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
static const unsigned int GreedyMotionSense = 30; #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 void
greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P, greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2,
uint8_t * Dest, int size) uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size)
{ {
int Pos; int Pos;
uint8_t l1_l, l1_1_l, l3_l, l3_1_l; 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, l2_c, lp2_l, lp2_c;
uint8_t l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff; uint8_t l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff;
uint8_t min_l, min_c, max_l, max_c; 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) { for (Pos = 0; Pos < size; Pos += 2) {
l1_l = L1[0]; 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); max_l = MAX (l1_l, l3_l);
min_l = MIN (l1_l, l3_l); min_l = MIN (l1_l, l3_l);
if (max_l < 256 - GreedyMaxComb) if (max_l < 256 - max_comb)
max_l += GreedyMaxComb; max_l += max_comb;
else else
max_l = 255; max_l = 255;
if (min_l > GreedyMaxComb) if (min_l > max_comb)
min_l -= GreedyMaxComb; min_l -= max_comb;
else else
min_l = 0; min_l = 0;
max_c = MAX (l1_c, l3_c); max_c = MAX (l1_c, l3_c);
min_c = MIN (l1_c, l3_c); min_c = MIN (l1_c, l3_c);
if (max_c < 256 - GreedyMaxComb) if (max_c < 256 - max_comb)
max_c += GreedyMaxComb; max_c += max_comb;
else else
max_c = 255; max_c = 255;
if (min_c > GreedyMaxComb) if (min_c > max_comb)
min_c -= GreedyMaxComb; min_c -= max_comb;
else else
min_c = 0; 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 /* Do motion compensation for luma, i.e. how much
* the weave pixel differs */ * the weave pixel differs */
mov_l = ABS (l2_l - lp2_l); mov_l = ABS (l2_l - lp2_l);
if (mov_l > GreedyMotionThreshold) if (mov_l > motion_threshold)
mov_l -= GreedyMotionThreshold; mov_l -= motion_threshold;
else else
mov_l = 0; mov_l = 0;
mov_l = mov_l * GreedyMotionSense; mov_l = mov_l * motion_sense;
if (mov_l > 256) if (mov_l > 256)
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 #endif
static void 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, GstDeinterlaceMethodGreedyH *self =
uint8_t * Dest, int size); GST_DEINTERLACE_METHOD_GREEDY_H (d_method);
GstDeinterlaceMethodGreedyHClass *klass =
GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
int InfoIsOdd = 0; int InfoIsOdd = 0;
int Line; int Line;
unsigned int Pitch = object->field_stride; 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 *L2P; // ptr to prev Line2
unsigned char *Dest = GST_BUFFER_DATA (object->out_buf); 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 // 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.) // 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) { 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; Dest += object->output_stride;
memcpy (Dest, L3, object->line_length); memcpy (Dest, L3, object->line_length);
Dest += object->output_stride; Dest += object->output_stride;
@ -293,31 +304,115 @@ deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
} }
} }
static deinterlace_method_t greedyh_method = { G_DEFINE_TYPE (GstDeinterlaceMethodGreedyH, gst_deinterlace_method_greedy_h,
0, //DEINTERLACE_PLUGIN_API_VERSION, GST_TYPE_DEINTERLACE_METHOD);
"Motion Adaptive: Advanced Detection",
"AdaptiveAdvanced", enum
4, {
0, ARG_0,
0, ARG_MAX_COMB,
0, ARG_MOTION_THRESHOLD,
0, ARG_MOTION_SENSE
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."}
}; };
deinterlace_method_t * static void
dscaler_greedyh_get_method (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;
} }

View file

@ -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 */

View file

@ -2,6 +2,7 @@
* *
* GStreamer * GStreamer
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net> * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -27,10 +28,15 @@
#ifndef TVTIME_PLUGINS_H_INCLUDED #ifndef TVTIME_PLUGINS_H_INCLUDED
#define TVTIME_PLUGINS_H_INCLUDED #define TVTIME_PLUGINS_H_INCLUDED
deinterlace_method_t* dscaler_tomsmocomp_get_method( void ); #define GST_TYPE_DEINTERLACE_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ())
deinterlace_method_t* dscaler_greedyh_get_method( void ); #define GST_TYPE_DEINTERLACE_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ())
deinterlace_method_t* dscaler_greedyl_get_method( void ); #define GST_TYPE_DEINTERLACE_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ())
deinterlace_method_t* dscaler_vfir_get_method( void ); #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 linear_plugin_init( void );
//void scalerbob_plugin_init( void ); //void scalerbob_plugin_init( void );

View file

@ -1,5 +1,6 @@
/** /**
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net> * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -31,22 +32,28 @@
#include "tomsmocomp/tomsmocompmacros.h" #include "tomsmocomp/tomsmocompmacros.h"
#include "x86-64_macros.inc" #include "x86-64_macros.inc"
#define SearchEffortDefault 5 #define GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ())
#define UseStrangeBobDefault 0 #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; GType gst_deinterlace_method_tomsmocomp_get_type (void);
static int UseStrangeBob;
static int IsOdd; typedef struct
static const unsigned char *pWeaveSrc; {
static const unsigned char *pWeaveSrcP; GstDeinterlaceMethod parent;
static unsigned char *pWeaveDest;
static const unsigned char *pCopySrc; guint search_effort;
static const unsigned char *pCopySrcP; gboolean strange_bob;
static unsigned char *pCopyDest; } GstDeinterlaceMethodTomsMoComp;
static int src_pitch;
static int dst_pitch; typedef struct
static int rowsize; {
static int FldHeight; GstDeinterlaceMethodClass parent_class;
} GstDeinterlaceMethodTomsMoCompClass;
static int static int
Fieldcopy (void *dest, const void *src, size_t count, 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 SSE_TYPE
#undef FUNCT_NAME #undef FUNCT_NAME
static void G_DEFINE_TYPE (GstDeinterlaceMethodTomsMoComp,
tomsmocomp_init (void) gst_deinterlace_method_tomsmocomp, GST_TYPE_DEINTERLACE_METHOD);
enum
{ {
SearchEffort = SearchEffortDefault; ARG_0,
UseStrangeBob = UseStrangeBobDefault; ARG_SEARCH_EFFORT,
} ARG_STRANGE_BOB
};
static void 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 switch (prop_id) {
tomsmocomp_filter_3dnow (GstDeinterlace2 * object) case ARG_SEARCH_EFFORT:
{ self->search_effort = g_value_get_uint (value);
tomsmocompDScaler_3DNOW (object); break;
} case ARG_STRANGE_BOB:
self->strange_bob = g_value_get_boolean (value);
static void break;
tomsmocomp_filter_sse (GstDeinterlace2 * object) default:
{ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
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 ();
} }
} }
static deinterlace_method_t tomsmocompmethod = { static void
0, //DEINTERLACE_PLUGIN_API_VERSION, gst_deinterlace_method_tomsmocomp_get_property (GObject * object, guint prop_id,
"Motion Adaptive: Motion Search", GValue * value, GParamSpec * pspec)
"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)
{ {
tomsmocomp_init (); GstDeinterlaceMethodTomsMoComp *self =
return &tomsmocompmethod; 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;
} }

View file

@ -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 */

View file

@ -33,11 +33,11 @@
#endif #endif
#if defined(IS_SSE) #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) #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 #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 #endif
#include "TomsMoCompAll2.inc" #include "TomsMoCompAll2.inc"
@ -48,9 +48,32 @@
#undef USE_STRANGE_BOB #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 */ /* double stride do address just every odd/even scanline */
src_pitch = object->field_stride; src_pitch = object->field_stride;
dst_pitch = object->output_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 // copy 1st and last weave lines
Fieldcopy(pWeaveDest, pCopySrc, rowsize, Fieldcopy(pWeaveDest, pCopySrc, rowsize,
1, dst_pitch*2, src_pitch); 1, dst_pitch*2, src_pitch);

View file

@ -3,6 +3,7 @@
* GStreamer * GStreamer
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net> * Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
* Copyright (c) 2001, 2002, 2003 Fabrice Bellard. * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public * modify it under the terms of the GNU Library General Public
@ -36,6 +37,26 @@
#include "gstdeinterlace2.h" #include "gstdeinterlace2.h"
#include <string.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 * The MPEG2 spec uses a slightly harsher filter, they specify
* [-1 8 2 8 -1]. ffmpeg uses a similar filter but with more of * [-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 #endif
static void static void
deinterlace_frame_vfir (GstDeinterlace2 * object) deinterlace_frame_vfir (GstDeinterlaceMethod * d_method,
GstDeinterlace2 * object)
{ {
void (*func) (uint8_t * dst, uint8_t * lum_m4, GstDeinterlaceMethodVFIRClass *klass =
uint8_t * lum_m3, uint8_t * lum_m2, GST_DEINTERLACE_METHOD_VFIR_GET_CLASS (d_method);
uint8_t * lum_m1, uint8_t * lum, int size);
gint line = 0; gint line = 0;
uint8_t *cur_field, *last_field; uint8_t *cur_field, *last_field;
uint8_t *t0, *b0, *tt1, *m1, *bb1, *out_data; 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 = cur_field =
GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf); GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
last_field = last_field =
@ -173,7 +184,7 @@ deinterlace_frame_vfir (GstDeinterlace2 * object)
bb1 = tt1; 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; out_data += object->output_stride;
cur_field += object->field_stride; cur_field += object->field_stride;
last_field += object->field_stride; last_field += object->field_stride;
@ -189,31 +200,33 @@ deinterlace_frame_vfir (GstDeinterlace2 * object)
} }
} }
static deinterlace_method_t vfirmethod = { G_DEFINE_TYPE (GstDeinterlaceMethodVFIR, gst_deinterlace_method_vfir,
0, //DEINTERLACE_PLUGIN_API_VERSION, GST_TYPE_DEINTERLACE_METHOD);
"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.",
""}
};
deinterlace_method_t * static void
dscaler_vfir_get_method (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;
} }