diff --git a/gst/deinterlace2/Makefile.am b/gst/deinterlace2/Makefile.am index b8ed59e4fa..26952e2edc 100644 --- a/gst/deinterlace2/Makefile.am +++ b/gst/deinterlace2/Makefile.am @@ -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 \ diff --git a/gst/deinterlace2/gstdeinterlace2.c b/gst/deinterlace2/gstdeinterlace2.c index e42afaba69..4103cfb6df 100644 --- a/gst/deinterlace2/gstdeinterlace2.c +++ b/gst/deinterlace2/gstdeinterlace2.c @@ -1,7 +1,7 @@ /* * GStreamer * Copyright (C) 2005 Martin Eikermann - * Copyright (C) 2008 Sebastian Dröge + * Copyright (C) 2008 Sebastian Dröge * * 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; diff --git a/gst/deinterlace2/gstdeinterlace2.h b/gst/deinterlace2/gstdeinterlace2.h index b312037ce2..815e04ebb2 100644 --- a/gst/deinterlace2/gstdeinterlace2.h +++ b/gst/deinterlace2/gstdeinterlace2.h @@ -1,7 +1,7 @@ /* * GStreamer * Copyright (C) 2005 Martin Eikermann - * Copyright (C) 2008 Sebastian Dröge + * Copyright (C) 2008 Sebastian Dröge * * 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. diff --git a/gst/deinterlace2/tvtime/greedy.c b/gst/deinterlace2/tvtime/greedy.c index 904a24b32e..434c332fca 100644 --- a/gst/deinterlace2/tvtime/greedy.c +++ b/gst/deinterlace2/tvtime/greedy.c @@ -4,6 +4,8 @@ * Copyright (c) 2000 Tom Barry All rights reserved. * mmx.h port copyright (c) 2002 Billy Biggs . * + * Copyright (C) 2008 Sebastian Dröge + * * 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 +#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; } diff --git a/gst/deinterlace2/tvtime/greedyh.asm b/gst/deinterlace2/tvtime/greedyh.asm index 5deaedadd7..3cc889455c 100644 --- a/gst/deinterlace2/tvtime/greedyh.asm +++ b/gst/deinterlace2/tvtime/greedyh.asm @@ -2,6 +2,7 @@ * * GStreamer * Copyright (c) 2001 Tom Barry. All rights reserved. + * Copyright (C) 2008 Sebastian Dröge * * 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); } } diff --git a/gst/deinterlace2/tvtime/greedyh.c b/gst/deinterlace2/tvtime/greedyh.c index 72f4378181..530d62894e 100644 --- a/gst/deinterlace2/tvtime/greedyh.c +++ b/gst/deinterlace2/tvtime/greedyh.c @@ -2,6 +2,7 @@ * * GStreamer * Copyright (C) 2004 Billy Biggs + * Copyright (C) 2008 Sebastian Dröge * * 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 @@ -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; } diff --git a/gst/deinterlace2/tvtime/greedyh.h b/gst/deinterlace2/tvtime/greedyh.h deleted file mode 100644 index 1156836ad6..0000000000 --- a/gst/deinterlace2/tvtime/greedyh.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * - * GStreamer - * Copyright (C) 2004 Billy Biggs - * - * 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 */ diff --git a/gst/deinterlace2/tvtime/plugins.h b/gst/deinterlace2/tvtime/plugins.h index 0eb90c0bf4..19d9aed9ef 100644 --- a/gst/deinterlace2/tvtime/plugins.h +++ b/gst/deinterlace2/tvtime/plugins.h @@ -2,6 +2,7 @@ * * GStreamer * Copyright (C) 2004 Billy Biggs + * Copyright (C) 2008 Sebastian Dröge * * 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 ); diff --git a/gst/deinterlace2/tvtime/tomsmocomp.c b/gst/deinterlace2/tvtime/tomsmocomp.c index 65234c2c0c..7a0ba6b3b7 100644 --- a/gst/deinterlace2/tvtime/tomsmocomp.c +++ b/gst/deinterlace2/tvtime/tomsmocomp.c @@ -1,5 +1,6 @@ /** * Copyright (C) 2004 Billy Biggs + * Copyright (C) 2008 Sebastian Dröge * * 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; } diff --git a/gst/deinterlace2/tvtime/tomsmocomp.h b/gst/deinterlace2/tvtime/tomsmocomp.h deleted file mode 100644 index ca40ac4483..0000000000 --- a/gst/deinterlace2/tvtime/tomsmocomp.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright (C) 2004 Billy Biggs - * - * 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 */ diff --git a/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc b/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc index 2318f6a363..743b6e8d11 100644 --- a/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc +++ b/gst/deinterlace2/tvtime/tomsmocomp/TomsMoCompAll.inc @@ -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); diff --git a/gst/deinterlace2/tvtime/vfir.c b/gst/deinterlace2/tvtime/vfir.c index 3a56f8502d..fcfbaa6b39 100644 --- a/gst/deinterlace2/tvtime/vfir.c +++ b/gst/deinterlace2/tvtime/vfir.c @@ -3,6 +3,7 @@ * GStreamer * Copyright (C) 2004 Billy Biggs * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. + * Copyright (C) 2008 Sebastian Dröge * * 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 +#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; }