[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 \
tvtime/mmx.h \
tvtime/sse.h \
tvtime/greedyh.h \
tvtime/greedyh.asm \
tvtime/greedyhmacros.h \
tvtime/plugins.h \

View file

@ -1,7 +1,7 @@
/*
* GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de>
* Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -49,25 +49,56 @@ enum
ARG_FIELD_LAYOUT
};
#define GST_TYPE_DEINTERLACE2_METHOD (gst_deinterlace2_method_get_type ())
static GType
gst_deinterlace2_method_get_type (void)
{
static GType deinterlace2_method_type = 0;
G_DEFINE_TYPE (GstDeinterlaceMethod, gst_deinterlace_method, GST_TYPE_OBJECT);
static const GEnumValue method_types[] = {
{GST_DEINTERLACE2_TOM, "Toms Motion Compensation", "tomsmc"},
static void
gst_deinterlace_method_class_init (GstDeinterlaceMethodClass * klass)
{
klass->available = TRUE;
}
static void
gst_deinterlace_method_init (GstDeinterlaceMethod * self)
{
}
static void
gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self,
GstDeinterlace2 * object)
{
GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
klass->deinterlace_frame (self, object);
}
static gint
gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self)
{
GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
return klass->fields_required;
}
#define GST_TYPE_DEINTERLACE2_METHODS (gst_deinterlace2_methods_get_type ())
static GType
gst_deinterlace2_methods_get_type (void)
{
static GType deinterlace2_methods_type = 0;
static const GEnumValue methods_types[] = {
{GST_DEINTERLACE2_TOMSMOCOMP, "Toms Motion Compensation", "tomsmocomp"},
{GST_DEINTERLACE2_GREEDY_H, "Greedy High Motion", "greedyh"},
{GST_DEINTERLACE2_GREEDY_L, "Greedy Low Motion", "greedyl"},
{GST_DEINTERLACE2_VFIR, "Vertical Blur", "vfir"},
{0, NULL, NULL},
};
if (!deinterlace2_method_type) {
deinterlace2_method_type =
g_enum_register_static ("GstDeinterlace2Methods", method_types);
if (!deinterlace2_methods_type) {
deinterlace2_methods_type =
g_enum_register_static ("GstDeinterlace2Methods", methods_types);
}
return deinterlace2_method_type;
return deinterlace2_methods_type;
}
#define GST_TYPE_DEINTERLACE2_FIELDS (gst_deinterlace2_fields_get_type ())
@ -141,8 +172,66 @@ static const GstQueryType *gst_deinterlace2_src_query_types (GstPad * pad);
static void gst_deinterlace2_reset (GstDeinterlace2 * object);
GST_BOILERPLATE (GstDeinterlace2, gst_deinterlace2, GstElement,
GST_TYPE_ELEMENT);
static void gst_deinterlace2_child_proxy_interface_init (gpointer g_iface,
gpointer iface_data);
static void
_do_init (GType object_type)
{
const GInterfaceInfo child_proxy_interface_info = {
(GInterfaceInitFunc) gst_deinterlace2_child_proxy_interface_init,
NULL, /* interface_finalize */
NULL /* interface_data */
};
g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
&child_proxy_interface_info);
}
GST_BOILERPLATE_FULL (GstDeinterlace2, gst_deinterlace2, GstElement,
GST_TYPE_ELEMENT, _do_init);
static void
gst_deinterlace2_set_method (GstDeinterlace2 * object,
GstDeinterlace2Methods method)
{
if (object->method) {
gst_child_proxy_child_removed (GST_OBJECT (object),
GST_OBJECT (object->method));
gst_object_unparent (GST_OBJECT (object->method));
object->method = NULL;
}
switch (method) {
case GST_DEINTERLACE2_TOMSMOCOMP:
object->method = g_object_new (GST_TYPE_DEINTERLACE_TOMSMOCOMP, NULL);
break;
case GST_DEINTERLACE2_GREEDY_H:
object->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_H, NULL);
break;
case GST_DEINTERLACE2_GREEDY_L:
object->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_L, NULL);
break;
case GST_DEINTERLACE2_VFIR:
object->method = g_object_new (GST_TYPE_DEINTERLACE_VFIR, NULL);
break;
default:
GST_WARNING ("Invalid Deinterlacer Method");
return;
}
object->method_id = method;
gst_object_set_name (GST_OBJECT (object->method), "method");
gst_object_set_parent (GST_OBJECT (object->method), GST_OBJECT (object));
gst_child_proxy_child_added (GST_OBJECT (object),
GST_OBJECT (object->method));
/* TODO: if current method requires less fields in the history,
pop the diff from field_history.
*/
}
static void
gst_deinterlace2_base_init (gpointer klass)
@ -177,8 +266,9 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
g_param_spec_enum ("method",
"Method",
"Deinterlace Method",
GST_TYPE_DEINTERLACE2_METHOD,
GST_DEINTERLACE2_TOM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
GST_TYPE_DEINTERLACE2_METHODS,
GST_DEINTERLACE2_TOMSMOCOMP,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (gobject_class, ARG_FIELDS,
@ -202,6 +292,33 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
GST_DEBUG_FUNCPTR (gst_deinterlace2_change_state);
}
static GstObject *
gst_deinterlace2_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
guint index)
{
GstDeinterlace2 *self = GST_DEINTERLACE2 (child_proxy);
g_return_val_if_fail (index == 0, NULL);
return gst_object_ref (self->method);
}
static guint
gst_deinterlace2_child_proxy_get_children_count (GstChildProxy * child_proxy)
{
return 1;
}
static void
gst_deinterlace2_child_proxy_interface_init (gpointer g_iface,
gpointer iface_data)
{
GstChildProxyInterface *iface = g_iface;
iface->get_child_by_index = gst_deinterlace2_child_proxy_get_child_by_index;
iface->get_children_count = gst_deinterlace2_child_proxy_get_children_count;
}
static void
gst_deinterlace2_init (GstDeinterlace2 * object, GstDeinterlace2Class * klass)
{
@ -231,9 +348,7 @@ gst_deinterlace2_init (GstDeinterlace2 * object, GstDeinterlace2Class * klass)
gst_element_no_more_pads (GST_ELEMENT (object));
object->cpu_feature_flags = oil_cpu_get_flags ();
object->method = dscaler_tomsmocomp_get_method ();
gst_deinterlace2_set_method (object, GST_DEINTERLACE2_TOMSMOCOMP);
object->field_layout = GST_DEINTERLACE2_LAYOUT_AUTO;
object->fields = GST_DEINTERLACE2_ALL;
@ -275,37 +390,6 @@ gst_deinterlace2_reset (GstDeinterlace2 * object)
gst_deinterlace2_reset_history (object);
}
static void
gst_deinterlace2_set_method (GstDeinterlace2 * object,
GstDeinterlace2Methods method)
{
switch (method) {
case GST_DEINTERLACE2_TOM:
object->method_id = method;
object->method = dscaler_tomsmocomp_get_method ();
break;
case GST_DEINTERLACE2_GREEDY_H:
object->method_id = method;
object->method = dscaler_greedyh_get_method ();
break;
case GST_DEINTERLACE2_GREEDY_L:
object->method_id = method;
object->method = dscaler_greedyl_get_method ();
break;
case GST_DEINTERLACE2_VFIR:
object->method_id = method;
object->method = dscaler_vfir_get_method ();
break;
default:
GST_WARNING ("Invalid Deinterlacer Method");
}
/* TODO: if current method requires less fields in the history,
pop the diff from field_history.
*/
}
static void
gst_deinterlace2_set_property (GObject * _object, guint prop_id,
const GValue * value, GParamSpec * pspec)
@ -367,7 +451,14 @@ gst_deinterlace2_get_property (GObject * _object, guint prop_id,
static void
gst_deinterlace2_finalize (GObject * object)
{
gst_deinterlace2_reset (GST_DEINTERLACE2 (object));
GstDeinterlace2 *self = GST_DEINTERLACE2 (object);
gst_deinterlace2_reset (self);
if (self->method) {
gst_object_unparent (GST_OBJECT (self->method));
self->method = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -456,6 +547,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
GstDeinterlace2 *object = NULL;
GstClockTime timestamp;
GstFlowReturn ret = GST_FLOW_OK;
gint fields_required = 0;
object = GST_DEINTERLACE2 (GST_PAD_PARENT (pad));
@ -464,9 +556,11 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
if (object->method != NULL) {
int cur_field_idx = 0;
fields_required =
gst_deinterlace_method_get_fields_required (object->method);
/* Not enough fields in the history */
if (object->history_count < object->method->fields_required + 1) {
if (object->history_count < fields_required + 1) {
/* TODO: do bob or just forward frame */
GST_DEBUG ("HistoryCount=%d", object->history_count);
return GST_FLOW_OK;
@ -479,7 +573,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
if (object->fields == GST_DEINTERLACE2_BF)
GST_DEBUG ("Bottom fields");
cur_field_idx = object->history_count - object->method->fields_required;
cur_field_idx = object->history_count - fields_required;
if ((object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_TOP
&& object->fields == GST_DEINTERLACE2_TF) ||
@ -494,8 +588,7 @@ 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);
@ -513,7 +606,6 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
if (ret != GST_FLOW_OK)
return ret;
}
}
/* no calculation done: remove excess field */
else if (object->field_history[cur_field_idx].flags ==
PICTURE_INTERLACED_TOP && object->fields == GST_DEINTERLACE2_BF) {
@ -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,8 +630,7 @@ 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);
@ -558,7 +649,6 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
if (ret != GST_FLOW_OK)
return ret;
}
}
/* no calculation done: remove excess field */
else if (object->field_history[cur_field_idx].flags ==
PICTURE_INTERLACED_BOTTOM && object->fields == GST_DEINTERLACE2_TF) {
@ -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;

View file

@ -1,7 +1,7 @@
/*
* GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de>
* Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -45,29 +45,40 @@ G_BEGIN_DECLS
typedef struct _GstDeinterlace2 GstDeinterlace2;
typedef struct _GstDeinterlace2Class GstDeinterlace2Class;
typedef struct deinterlace_setting_s deinterlace_setting_t;
typedef struct deinterlace_method_s deinterlace_method_t;
#define GST_TYPE_DEINTERLACE_METHOD (gst_deinterlace_method_get_type ())
#define GST_IS_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD))
#define GST_IS_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD))
#define GST_DEINTERLACE_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass))
#define GST_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethod))
#define GST_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass))
#define GST_DEINTERLACE_METHOD_CAST(obj) ((GstDeinterlaceMethod*)(obj))
typedef void (*deinterlace_frame_t) (GstDeinterlace2 * object);
typedef struct _GstDeinterlaceMethod GstDeinterlaceMethod;
typedef struct _GstDeinterlaceMethodClass GstDeinterlaceMethodClass;
/*
* This structure defines the deinterlacer plugin.
*/
struct deinterlace_method_s
{
int version;
const char *name;
const char *short_name;
int fields_required;
int accelrequired;
int doscalerbob;
int numsettings;
deinterlace_setting_t *settings;
int scanlinemode;
deinterlace_frame_t deinterlace_frame;
const char *description[10];
struct _GstDeinterlaceMethod {
GstObject parent;
};
struct _GstDeinterlaceMethodClass {
GstObjectClass parent_class;
guint fields_required;
guint latency;
gboolean available;
void (*deinterlace_frame) (GstDeinterlaceMethod *self, GstDeinterlace2 * object);
const gchar *name;
const gchar *nick;
};
GType gst_deinterlace_method_get_type (void);
#define MAX_FIELD_HISTORY 10
#define PICTURE_PROGRESSIVE 0
@ -75,8 +86,6 @@ struct deinterlace_method_s
#define PICTURE_INTERLACED_TOP 2
#define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP)
typedef void (MEMCPY_FUNC) (void *pOutput, const void *pInput, size_t nSize);
typedef struct
{
/* pointer to the start of data for this field */
@ -87,7 +96,7 @@ typedef struct
typedef enum
{
GST_DEINTERLACE2_TOM,
GST_DEINTERLACE2_TOMSMOCOMP,
GST_DEINTERLACE2_GREEDY_H,
GST_DEINTERLACE2_GREEDY_L,
GST_DEINTERLACE2_VFIR
@ -115,7 +124,6 @@ struct _GstDeinterlace2
guint history_count;
guint cpu_feature_flags;
GstDeinterlace2FieldLayout field_layout;
guint frame_size;
@ -124,7 +132,7 @@ struct _GstDeinterlace2
GstDeinterlace2Fields fields;
GstDeinterlace2Methods method_id;
deinterlace_method_t *method;
GstDeinterlaceMethod *method;
/* The most recent pictures
PictureHistory[0] is always the most recent.

View file

@ -4,6 +4,8 @@
* Copyright (c) 2000 Tom Barry All rights reserved.
* mmx.h port copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>.
*
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
@ -35,6 +37,30 @@
#include "gstdeinterlace2.h"
#include <string.h>
#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ())
#define GST_IS_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L))
#define GST_IS_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L))
#define GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass))
#define GST_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyL))
#define GST_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass))
#define GST_DEINTERLACE_METHOD_GREEDY_L_CAST(obj) ((GstDeinterlaceMethodGreedyL*)(obj))
GType gst_deinterlace_method_greedy_l_get_type (void);
typedef struct
{
GstDeinterlaceMethod parent;
guint max_comb;
} GstDeinterlaceMethodGreedyL;
typedef struct
{
GstDeinterlaceMethodClass parent_class;
void (*scanline) (GstDeinterlaceMethodGreedyL * self, uint8_t * L2,
uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size);
} GstDeinterlaceMethodGreedyLClass;
// This is a simple lightweight DeInterlace method that uses little CPU time
// but gives very good results for low or intermedite motion.
// It defers frames by one field, but that does not seem to produce noticeable
@ -47,13 +73,13 @@
// I'd intended this to be part of a larger more elaborate method added to
// Blended Clip but this give too good results for the CPU to ignore here.
static const int GreedyMaxComb = 15;
static inline void
deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
deinterlace_greedy_packed422_scanline_c (GstDeinterlaceMethodGreedyL * self,
uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{
int avg, l2_diff, lp2_diff, max, min, best;
guint max_comb = self->max_comb;
// L2 == m0
// L1 == t1
@ -74,13 +100,13 @@ deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
max = MAX (*t1, *b1);
min = MIN (*t1, *b1);
if (max < 256 - GreedyMaxComb)
max += GreedyMaxComb;
if (max < 256 - max_comb)
max += max_comb;
else
max = 255;
if (min > GreedyMaxComb)
min -= GreedyMaxComb;
if (min > max_comb)
min -= max_comb;
else
min = 0;
@ -98,22 +124,22 @@ deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
#ifdef HAVE_CPU_I386
#include "mmx.h"
static void
deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
deinterlace_greedy_packed422_scanline_mmx (GstDeinterlaceMethodGreedyL * self,
uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{
mmx_t MaxComb;
mmx_t ShiftMask;
// How badly do we let it weave? 0-255
MaxComb.ub[0] = GreedyMaxComb;
MaxComb.ub[1] = GreedyMaxComb;
MaxComb.ub[2] = GreedyMaxComb;
MaxComb.ub[3] = GreedyMaxComb;
MaxComb.ub[4] = GreedyMaxComb;
MaxComb.ub[5] = GreedyMaxComb;
MaxComb.ub[6] = GreedyMaxComb;
MaxComb.ub[7] = GreedyMaxComb;
MaxComb.ub[0] = self->max_comb;
MaxComb.ub[1] = self->max_comb;
MaxComb.ub[2] = self->max_comb;
MaxComb.ub[3] = self->max_comb;
MaxComb.ub[4] = self->max_comb;
MaxComb.ub[5] = self->max_comb;
MaxComb.ub[6] = self->max_comb;
MaxComb.ub[7] = self->max_comb;
ShiftMask.ub[0] = 0x7f;
ShiftMask.ub[1] = 0x7f;
@ -207,26 +233,28 @@ deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
}
emms ();
if (width > 0)
deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output,
width);
}
#include "sse.h"
static void
deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlaceMethodGreedyL *
self, uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2,
uint8_t * output, int width)
{
mmx_t MaxComb;
// How badly do we let it weave? 0-255
MaxComb.ub[0] = GreedyMaxComb;
MaxComb.ub[1] = GreedyMaxComb;
MaxComb.ub[2] = GreedyMaxComb;
MaxComb.ub[3] = GreedyMaxComb;
MaxComb.ub[4] = GreedyMaxComb;
MaxComb.ub[5] = GreedyMaxComb;
MaxComb.ub[6] = GreedyMaxComb;
MaxComb.ub[7] = GreedyMaxComb;
MaxComb.ub[0] = self->max_comb;
MaxComb.ub[1] = self->max_comb;
MaxComb.ub[2] = self->max_comb;
MaxComb.ub[3] = self->max_comb;
MaxComb.ub[4] = self->max_comb;
MaxComb.ub[5] = self->max_comb;
MaxComb.ub[6] = self->max_comb;
MaxComb.ub[7] = self->max_comb;
// L2 == m0
// L1 == t1
@ -299,17 +327,20 @@ deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1,
emms ();
if (width > 0)
deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output,
width);
}
#endif
static void
deinterlace_frame_di_greedy (GstDeinterlace2 * object)
deinterlace_frame_di_greedy (GstDeinterlaceMethod * d_method,
GstDeinterlace2 * object)
{
void (*func) (uint8_t * L2, uint8_t * L1, uint8_t * L3, uint8_t * L2P,
uint8_t * Dest, int size);
GstDeinterlaceMethodGreedyL *self =
GST_DEINTERLACE_METHOD_GREEDY_L (d_method);
GstDeinterlaceMethodGreedyLClass *klass =
GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS (self);
int InfoIsOdd = 0;
int Line;
unsigned int Pitch = object->field_stride;
@ -320,18 +351,6 @@ deinterlace_frame_di_greedy (GstDeinterlace2 * object)
unsigned char *L2P; // ptr to prev Line2
unsigned char *Dest = GST_BUFFER_DATA (object->out_buf);
#ifdef HAVE_CPU_I386
if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMXEXT) {
func = deinterlace_greedy_packed422_scanline_mmxext;
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
func = deinterlace_greedy_packed422_scanline_mmx;
} else {
func = deinterlace_greedy_packed422_scanline_c;
}
#else
func = deinterlace_greedy_packed422_scanline_c;
#endif
// copy first even line no matter what, and the first odd line if we're
// processing an EVEN field. (note diff from other deint rtns.)
@ -368,7 +387,7 @@ deinterlace_frame_di_greedy (GstDeinterlace2 * object)
}
for (Line = 0; Line < (object->field_height - 1); ++Line) {
func (L2, L1, L3, L2P, Dest, object->line_length);
klass->scanline (self, L2, L1, L3, L2P, Dest, object->line_length);
Dest += object->output_stride;
memcpy (Dest, L3, object->line_length);
Dest += object->output_stride;
@ -384,31 +403,84 @@ deinterlace_frame_di_greedy (GstDeinterlace2 * object)
}
}
static deinterlace_method_t greedyl_method = {
0, //DEINTERLACE_PLUGIN_API_VERSION,
"Motion Adaptive: Simple Detection",
"AdaptiveSimple",
4,
0,
0,
0,
0,
1,
deinterlace_frame_di_greedy,
{"Uses heuristics to detect motion in the input",
"frames and reconstruct image detail where",
"possible. Use this for high quality output",
"even on monitors set to an arbitrary refresh",
"rate.",
"",
"Simple detection uses linear interpolation",
"where motion is detected, using a two-field",
"buffer. This is the Greedy: Low Motion",
"deinterlacer from DScaler."}
G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l,
GST_TYPE_DEINTERLACE_METHOD);
enum
{
ARG_0,
ARG_MAX_COMB
};
deinterlace_method_t *
dscaler_greedyl_get_method (void)
static void
gst_deinterlace_method_greedy_l_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
return &greedyl_method;
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object);
switch (prop_id) {
case ARG_MAX_COMB:
self->max_comb = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_deinterlace_method_greedy_l_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object);
switch (prop_id) {
case ARG_MAX_COMB:
g_value_set_uint (value, self->max_comb);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass *
klass)
{
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
GObjectClass *gobject_class = (GObjectClass *) klass;
guint cpu_flags = oil_cpu_get_flags ();
gobject_class->set_property = gst_deinterlace_method_greedy_l_set_property;
gobject_class->get_property = gst_deinterlace_method_greedy_l_get_property;
g_object_class_install_property (gobject_class, ARG_MAX_COMB,
g_param_spec_uint ("max-comb",
"Max comb",
"Max Comb", 0, 255, 15, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
dim_class->fields_required = 4;
dim_class->deinterlace_frame = deinterlace_frame_di_greedy;
dim_class->name = "Motion Adaptive: Simple Detection";
dim_class->nick = "greedyl";
dim_class->latency = 1;
#ifdef HAVE_CPU_I386
if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
klass->scanline = deinterlace_greedy_packed422_scanline_mmxext;
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
klass->scanline = deinterlace_greedy_packed422_scanline_mmx;
} else {
klass->scanline = deinterlace_greedy_packed422_scanline_c;
}
#else
klass->scanline = deinterlace_greedy_packed422_scanline_c;
#endif
}
static void
gst_deinterlace_method_greedy_l_init (GstDeinterlaceMethodGreedyL * self)
{
self->max_comb = 15;
}

View file

@ -2,6 +2,7 @@
*
* GStreamer
* Copyright (c) 2001 Tom Barry. All rights reserved.
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -29,7 +30,7 @@
#include "x86-64_macros.inc"
void
FUNCT_NAME (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
FUNCT_NAME (GstDeinterlaceMethodGreedyH *self, uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
uint8_t * Dest, int size)
{
@ -49,14 +50,14 @@ FUNCT_NAME (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
int64_t LastAvg = 0; //interp value from left qword
// Set up our two parms that are actually evaluated for each pixel
i = GreedyMaxComb;
i = self->max_comb;
MaxComb =
i << 56 | i << 48 | i << 40 | i << 32 | i << 24 | i << 16 | i << 8 | i;
i = GreedyMotionThreshold; // scale to range of 0-257
i = self->motion_threshold; // scale to range of 0-257
MotionThreshold = i << 48 | i << 32 | i << 16 | i | UVMask;
i = GreedyMotionSense; // scale to range of 0-257
i = self->motion_sense; // scale to range of 0-257
MotionSense = i << 48 | i << 32 | i << 16 | i;
i = 0xffffffff - 256;
@ -243,6 +244,6 @@ FUNCT_NAME (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
if (size % 8 != 0) {
int offset = GST_ROUND_DOWN_8 (size);
greedyDScaler_C (L1 + offset, L2 + offset, L3 + offset, L2P + offset, Dest + offset, size % 8);
greedyDScaler_C (self, L1 + offset, L2 + offset, L3 + offset, L2P + offset, Dest + offset, size % 8);
}
}

View file

@ -2,6 +2,7 @@
*
* GStreamer
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -28,7 +29,6 @@
# include "config.h"
#endif
#include "greedyh.h"
#include "greedyhmacros.h"
#include <stdlib.h>
@ -39,13 +39,33 @@
#include "plugins.h"
#include "gstdeinterlace2.h"
static const unsigned int GreedyMaxComb = 5;
static const unsigned int GreedyMotionThreshold = 25;
static const unsigned int GreedyMotionSense = 30;
#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_H (gst_deinterlace_method_greedy_h_get_type ())
#define GST_IS_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
#define GST_IS_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H))
#define GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass))
#define GST_DEINTERLACE_METHOD_GREEDY_H(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyH))
#define GST_DEINTERLACE_METHOD_GREEDY_H_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_H, GstDeinterlaceMethodGreedyHClass))
#define GST_DEINTERLACE_METHOD_GREEDY_H_CAST(obj) ((GstDeinterlaceMethodGreedyH*)(obj))
GType gst_deinterlace_method_greedy_h_get_type (void);
typedef struct
{
GstDeinterlaceMethod parent;
guint max_comb, motion_threshold, motion_sense;
} GstDeinterlaceMethodGreedyH;
typedef struct
{
GstDeinterlaceMethodClass parent_class;
void (*scanline) (GstDeinterlaceMethodGreedyH * self, uint8_t * L2,
uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size);
} GstDeinterlaceMethodGreedyHClass;
void
greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
uint8_t * Dest, int size)
greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2,
uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size)
{
int Pos;
uint8_t l1_l, l1_1_l, l3_l, l3_1_l;
@ -60,6 +80,9 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
uint8_t l2_l, l2_c, lp2_l, lp2_c;
uint8_t l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff;
uint8_t min_l, min_c, max_l, max_c;
guint max_comb = self->max_comb;
guint motion_sense = self->motion_sense;
guint motion_threshold = self->motion_threshold;
for (Pos = 0; Pos < size; Pos += 2) {
l1_l = L1[0];
@ -130,26 +153,26 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
max_l = MAX (l1_l, l3_l);
min_l = MIN (l1_l, l3_l);
if (max_l < 256 - GreedyMaxComb)
max_l += GreedyMaxComb;
if (max_l < 256 - max_comb)
max_l += max_comb;
else
max_l = 255;
if (min_l > GreedyMaxComb)
min_l -= GreedyMaxComb;
if (min_l > max_comb)
min_l -= max_comb;
else
min_l = 0;
max_c = MAX (l1_c, l3_c);
min_c = MIN (l1_c, l3_c);
if (max_c < 256 - GreedyMaxComb)
max_c += GreedyMaxComb;
if (max_c < 256 - max_comb)
max_c += max_comb;
else
max_c = 255;
if (min_c > GreedyMaxComb)
min_c -= GreedyMaxComb;
if (min_c > max_comb)
min_c -= max_comb;
else
min_c = 0;
@ -159,12 +182,12 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
/* Do motion compensation for luma, i.e. how much
* the weave pixel differs */
mov_l = ABS (l2_l - lp2_l);
if (mov_l > GreedyMotionThreshold)
mov_l -= GreedyMotionThreshold;
if (mov_l > motion_threshold)
mov_l -= motion_threshold;
else
mov_l = 0;
mov_l = mov_l * GreedyMotionSense;
mov_l = mov_l * motion_sense;
if (mov_l > 256)
mov_l = 256;
@ -211,11 +234,13 @@ greedyDScaler_C (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
#endif
static void
deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
deinterlace_frame_di_greedyh (GstDeinterlaceMethod * d_method,
GstDeinterlace2 * object)
{
void (*func) (uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
uint8_t * Dest, int size);
GstDeinterlaceMethodGreedyH *self =
GST_DEINTERLACE_METHOD_GREEDY_H (d_method);
GstDeinterlaceMethodGreedyHClass *klass =
GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
int InfoIsOdd = 0;
int Line;
unsigned int Pitch = object->field_stride;
@ -227,20 +252,6 @@ deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
unsigned char *L2P; // ptr to prev Line2
unsigned char *Dest = GST_BUFFER_DATA (object->out_buf);
#ifdef HAVE_CPU_I386
if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMXEXT) {
func = greedyDScaler_MMXEXT;
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_3DNOW) {
func = greedyDScaler_3DNOW;
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
func = greedyDScaler_MMX;
} else {
func = greedyDScaler_C;
}
#else
func = greedyDScaler_C;
#endif
// copy first even line no matter what, and the first odd line if we're
// processing an EVEN field. (note diff from other deint rtns.)
@ -277,7 +288,7 @@ deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
}
for (Line = 0; Line < (object->field_height - 1); ++Line) {
func (L1, L2, L3, L2P, Dest, object->line_length);
klass->scanline (self, L1, L2, L3, L2P, Dest, object->line_length);
Dest += object->output_stride;
memcpy (Dest, L3, object->line_length);
Dest += object->output_stride;
@ -293,31 +304,115 @@ deinterlace_frame_di_greedyh (GstDeinterlace2 * object)
}
}
static deinterlace_method_t greedyh_method = {
0, //DEINTERLACE_PLUGIN_API_VERSION,
"Motion Adaptive: Advanced Detection",
"AdaptiveAdvanced",
4,
0,
0,
0,
0,
0,
deinterlace_frame_di_greedyh,
{"Uses heuristics to detect motion in the input",
"frames and reconstruct image detail where",
"possible. Use this for high quality output",
"even on monitors set to an arbitrary refresh",
"rate.",
"",
"Advanced detection uses linear interpolation",
"where motion is detected, using a four-field",
"buffer. This is the Greedy: High Motion",
"deinterlacer from DScaler."}
G_DEFINE_TYPE (GstDeinterlaceMethodGreedyH, gst_deinterlace_method_greedy_h,
GST_TYPE_DEINTERLACE_METHOD);
enum
{
ARG_0,
ARG_MAX_COMB,
ARG_MOTION_THRESHOLD,
ARG_MOTION_SENSE
};
deinterlace_method_t *
dscaler_greedyh_get_method (void)
static void
gst_deinterlace_method_greedy_h_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
return &greedyh_method;
GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
switch (prop_id) {
case ARG_MAX_COMB:
self->max_comb = g_value_get_uint (value);
break;
case ARG_MOTION_THRESHOLD:
self->motion_threshold = g_value_get_uint (value);
break;
case ARG_MOTION_SENSE:
self->motion_sense = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_deinterlace_method_greedy_h_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
switch (prop_id) {
case ARG_MAX_COMB:
g_value_set_uint (value, self->max_comb);
break;
case ARG_MOTION_THRESHOLD:
g_value_set_uint (value, self->motion_threshold);
break;
case ARG_MOTION_SENSE:
g_value_set_uint (value, self->motion_sense);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass *
klass)
{
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
GObjectClass *gobject_class = (GObjectClass *) klass;
guint cpu_flags = oil_cpu_get_flags ();
gobject_class->set_property = gst_deinterlace_method_greedy_h_set_property;
gobject_class->get_property = gst_deinterlace_method_greedy_h_get_property;
g_object_class_install_property (gobject_class, ARG_MAX_COMB,
g_param_spec_uint ("max-comb",
"Max comb",
"Max Comb", 0, 255, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (gobject_class, ARG_MOTION_THRESHOLD,
g_param_spec_uint ("motion-threshold",
"Motion Threshold",
"Motion Threshold",
0, 255, 25, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (gobject_class, ARG_MOTION_SENSE,
g_param_spec_uint ("motion-sense",
"Motion Sense",
"Motion Sense",
0, 255, 30, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
dim_class->fields_required = 4;
dim_class->deinterlace_frame = deinterlace_frame_di_greedyh;
dim_class->name = "Motion Adaptive: Advanced Detection";
dim_class->nick = "greedyh";
dim_class->latency = 1;
#ifdef HAVE_CPU_I386
if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
klass->scanline = greedyDScaler_MMXEXT;
} else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) {
klass->scanline = greedyDScaler_3DNOW;
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
klass->scanline = greedyDScaler_MMX;
} else {
klass->scanline = greedyDScaler_C;
}
#else
klass->scanline = greedyDScaler_C;
#endif
}
static void
gst_deinterlace_method_greedy_h_init (GstDeinterlaceMethodGreedyH * self)
{
self->max_comb = 5;
self->motion_threshold = 25;
self->motion_sense = 30;
}

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

View file

@ -1,5 +1,6 @@
/**
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -31,22 +32,28 @@
#include "tomsmocomp/tomsmocompmacros.h"
#include "x86-64_macros.inc"
#define SearchEffortDefault 5
#define UseStrangeBobDefault 0
#define GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP (gst_deinterlace_method_tomsmocomp_get_type ())
#define GST_IS_DEINTERLACE_METHOD_TOMSMOCOMP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP))
#define GST_IS_DEINTERLACE_METHOD_TOMSMOCOMP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP))
#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoCompClass))
#define GST_DEINTERLACE_METHOD_TOMSMOCOMP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoComp))
#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_TOMSMOCOMP, GstDeinterlaceMethodTomsMoCompClass))
#define GST_DEINTERLACE_METHOD_TOMSMOCOMP_CAST(obj) ((GstDeinterlaceMethodTomsMoComp*)(obj))
static long SearchEffort;
static int UseStrangeBob;
static int IsOdd;
static const unsigned char *pWeaveSrc;
static const unsigned char *pWeaveSrcP;
static unsigned char *pWeaveDest;
static const unsigned char *pCopySrc;
static const unsigned char *pCopySrcP;
static unsigned char *pCopyDest;
static int src_pitch;
static int dst_pitch;
static int rowsize;
static int FldHeight;
GType gst_deinterlace_method_tomsmocomp_get_type (void);
typedef struct
{
GstDeinterlaceMethod parent;
guint search_effort;
gboolean strange_bob;
} GstDeinterlaceMethodTomsMoComp;
typedef struct
{
GstDeinterlaceMethodClass parent_class;
} GstDeinterlaceMethodTomsMoCompClass;
static int
Fieldcopy (void *dest, const void *src, size_t count,
@ -90,71 +97,96 @@ Fieldcopy (void *dest, const void *src, size_t count,
#undef SSE_TYPE
#undef FUNCT_NAME
static void
tomsmocomp_init (void)
G_DEFINE_TYPE (GstDeinterlaceMethodTomsMoComp,
gst_deinterlace_method_tomsmocomp, GST_TYPE_DEINTERLACE_METHOD);
enum
{
SearchEffort = SearchEffortDefault;
UseStrangeBob = UseStrangeBobDefault;
}
ARG_0,
ARG_SEARCH_EFFORT,
ARG_STRANGE_BOB
};
static void
tomsmocomp_filter_mmx (GstDeinterlace2 * object)
gst_deinterlace_method_tomsmocomp_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
tomsmocompDScaler_MMX (object);
}
GstDeinterlaceMethodTomsMoComp *self =
GST_DEINTERLACE_METHOD_TOMSMOCOMP (object);
static void
tomsmocomp_filter_3dnow (GstDeinterlace2 * object)
{
tomsmocompDScaler_3DNOW (object);
}
static void
tomsmocomp_filter_sse (GstDeinterlace2 * object)
{
tomsmocompDScaler_SSE (object);
}
static void
deinterlace_frame_di_tomsmocomp (GstDeinterlace2 * object)
{
if (object->cpu_feature_flags & OIL_IMPL_FLAG_SSE) {
tomsmocomp_filter_sse (object);
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_3DNOW) {
tomsmocomp_filter_3dnow (object);
} else if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
tomsmocomp_filter_mmx (object);
} else {
g_assert_not_reached ();
switch (prop_id) {
case ARG_SEARCH_EFFORT:
self->search_effort = g_value_get_uint (value);
break;
case ARG_STRANGE_BOB:
self->strange_bob = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static deinterlace_method_t tomsmocompmethod = {
0, //DEINTERLACE_PLUGIN_API_VERSION,
"Motion Adaptive: Motion Search",
"AdaptiveSearch",
4,
OIL_IMPL_FLAG_MMX,
0,
0,
0,
0,
deinterlace_frame_di_tomsmocomp,
{"Uses heuristics to detect motion in the input",
"frames and reconstruct image detail where",
"possible. Use this for high quality output",
"even on monitors set to an arbitrary refresh",
"rate.",
"",
"Motion search mode finds and follows motion",
"vectors for accurate interpolation. This is",
"the TomsMoComp deinterlacer from DScaler.",
""}
};
deinterlace_method_t *
dscaler_tomsmocomp_get_method (void)
static void
gst_deinterlace_method_tomsmocomp_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
tomsmocomp_init ();
return &tomsmocompmethod;
GstDeinterlaceMethodTomsMoComp *self =
GST_DEINTERLACE_METHOD_TOMSMOCOMP (object);
switch (prop_id) {
case ARG_SEARCH_EFFORT:
g_value_set_uint (value, self->search_effort);
break;
case ARG_STRANGE_BOB:
g_value_set_boolean (value, self->strange_bob);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
gst_deinterlace_method_tomsmocomp_class_init
(GstDeinterlaceMethodTomsMoCompClass * klass)
{
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
GObjectClass *gobject_class = (GObjectClass *) klass;
guint cpu_flags = oil_cpu_get_flags ();
gobject_class->set_property = gst_deinterlace_method_tomsmocomp_set_property;
gobject_class->get_property = gst_deinterlace_method_tomsmocomp_get_property;
g_object_class_install_property (gobject_class, ARG_SEARCH_EFFORT,
g_param_spec_uint ("search-effort",
"Search Effort",
"Search Effort", 0, 27, 5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (gobject_class, ARG_STRANGE_BOB,
g_param_spec_boolean ("strange-bob",
"Strange Bob",
"Use strange bob", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
dim_class->fields_required = 4;
dim_class->name = "Motion Adaptive: Motion Search";
dim_class->nick = "tomsmocomp";
dim_class->latency = 1;
if (cpu_flags & OIL_IMPL_FLAG_SSE) {
dim_class->deinterlace_frame = tomsmocompDScaler_SSE;
} else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) {
dim_class->deinterlace_frame = tomsmocompDScaler_3DNOW;
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
dim_class->deinterlace_frame = tomsmocompDScaler_MMX;
} else {
dim_class->available = FALSE;
}
}
static void
gst_deinterlace_method_tomsmocomp_init (GstDeinterlaceMethodTomsMoComp * self)
{
self->search_effort = 5;
self->strange_bob = FALSE;
}

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
#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);

View file

@ -3,6 +3,7 @@
* GStreamer
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
* Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -36,6 +37,26 @@
#include "gstdeinterlace2.h"
#include <string.h>
#define GST_TYPE_DEINTERLACE_METHOD_VFIR (gst_deinterlace_method_vfir_get_type ())
#define GST_IS_DEINTERLACE_METHOD_VFIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR))
#define GST_IS_DEINTERLACE_METHOD_VFIR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_VFIR))
#define GST_DEINTERLACE_METHOD_VFIR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIRClass))
#define GST_DEINTERLACE_METHOD_VFIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIR))
#define GST_DEINTERLACE_METHOD_VFIR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_VFIR, GstDeinterlaceMethodVFIRClass))
#define GST_DEINTERLACE_METHOD_VFIR_CAST(obj) ((GstDeinterlaceMethodVFIR*)(obj))
GType gst_deinterlace_method_vfir_get_type (void);
typedef GstDeinterlaceMethod GstDeinterlaceMethodVFIR;
typedef struct
{
GstDeinterlaceMethodClass parent_class;
void (*scanline) (uint8_t * dst, uint8_t * lum_m4,
uint8_t * lum_m3, uint8_t * lum_m2,
uint8_t * lum_m1, uint8_t * lum, int size);
} GstDeinterlaceMethodVFIRClass;
/*
* The MPEG2 spec uses a slightly harsher filter, they specify
* [-1 8 2 8 -1]. ffmpeg uses a similar filter but with more of
@ -122,25 +143,15 @@ deinterlace_line_mmx (uint8_t * dst, uint8_t * lum_m4,
#endif
static void
deinterlace_frame_vfir (GstDeinterlace2 * object)
deinterlace_frame_vfir (GstDeinterlaceMethod * d_method,
GstDeinterlace2 * object)
{
void (*func) (uint8_t * dst, uint8_t * lum_m4,
uint8_t * lum_m3, uint8_t * lum_m2,
uint8_t * lum_m1, uint8_t * lum, int size);
GstDeinterlaceMethodVFIRClass *klass =
GST_DEINTERLACE_METHOD_VFIR_GET_CLASS (d_method);
gint line = 0;
uint8_t *cur_field, *last_field;
uint8_t *t0, *b0, *tt1, *m1, *bb1, *out_data;
#ifdef HAVE_CPU_I386
if (object->cpu_feature_flags & OIL_IMPL_FLAG_MMX) {
func = deinterlace_line_mmx;
} else {
func = deinterlace_line_c;
}
#else
func = deinterlace_line_c;
#endif
cur_field =
GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
last_field =
@ -173,7 +184,7 @@ deinterlace_frame_vfir (GstDeinterlace2 * object)
bb1 = tt1;
}
func (out_data, tt1, t0, m1, b0, bb1, object->line_length);
klass->scanline (out_data, tt1, t0, m1, b0, bb1, object->line_length);
out_data += object->output_stride;
cur_field += object->field_stride;
last_field += object->field_stride;
@ -189,31 +200,33 @@ deinterlace_frame_vfir (GstDeinterlace2 * object)
}
}
static deinterlace_method_t vfirmethod = {
0, //DEINTERLACE_PLUGIN_API_VERSION,
"Blur: Vertical",
"BlurVertical",
2,
0,
0,
0,
0,
1,
deinterlace_frame_vfir,
{"Avoids flicker by blurring consecutive frames",
"of input. Use this if you want to run your",
"monitor at an arbitrary refresh rate and not",
"use much CPU, and are willing to sacrifice",
"detail.",
"",
"Vertical mode blurs favouring the most recent",
"field for less visible trails. From the",
"deinterlacer filter in ffmpeg.",
""}
};
G_DEFINE_TYPE (GstDeinterlaceMethodVFIR, gst_deinterlace_method_vfir,
GST_TYPE_DEINTERLACE_METHOD);
deinterlace_method_t *
dscaler_vfir_get_method (void)
static void
gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass)
{
GstDeinterlaceMethodClass *dim_class = (GstDeinterlaceMethodClass *) klass;
guint cpu_flags = oil_cpu_get_flags ();
dim_class->fields_required = 2;
dim_class->deinterlace_frame = deinterlace_frame_vfir;
dim_class->name = "Blur Vertical";
dim_class->nick = "vfir";
dim_class->latency = 0;
#ifdef HAVE_CPU_I386
if (cpu_flags & OIL_IMPL_FLAG_MMX) {
klass->scanline = deinterlace_line_mmx;
} else {
klass->scanline = deinterlace_line_c;
}
#else
klass->scanline = deinterlace_line_c;
#endif
}
static void
gst_deinterlace_method_vfir_init (GstDeinterlaceMethodVFIR * self)
{
return &vfirmethod;
}