Commit fb7f06ad authored by Sebastian Dröge's avatar Sebastian Dröge 🍵 Committed by Sebastian Dröge
Browse files

[MOVED FROM BAD 23/56] gst/deinterlace2/: Use a GstObject subtype for the...

[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.
parent e5231e56
......@@ -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 \
......
/*
* GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de>
* Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -49,25 +49,56 @@ enum
ARG_FIELD_LAYOUT
};
#define GST_TYPE_DEINTERLACE2_METHOD (gst_deinterlace2_method_get_type ())
G_DEFINE_TYPE (GstDeinterlaceMethod, gst_deinterlace_method, GST_TYPE_OBJECT);
static void
gst_deinterlace_method_class_init (GstDeinterlaceMethodClass * klass)
{
klass->available = TRUE;
}
static void
gst_deinterlace_method_init (GstDeinterlaceMethod * self)
{
}
static void
gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self,
GstDeinterlace2 * object)
{
GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
klass->deinterlace_frame (self, object);
}
static gint
gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self)
{
GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
return klass->fields_required;
}
#define GST_TYPE_DEINTERLACE2_METHODS (gst_deinterlace2_methods_get_type ())
static GType
gst_deinterlace2_method_get_type (void)
gst_deinterlace2_methods_get_type (void)
{
static GType deinterlace2_method_type = 0;
static GType deinterlace2_methods_type = 0;
static const GEnumValue method_types[] = {
{GST_DEINTERLACE2_TOM, "Toms Motion Compensation", "tomsmc"},
static const GEnumValue methods_types[] = {
{GST_DEINTERLACE2_TOMSMOCOMP, "Toms Motion Compensation", "tomsmocomp"},
{GST_DEINTERLACE2_GREEDY_H, "Greedy High Motion", "greedyh"},
{GST_DEINTERLACE2_GREEDY_L, "Greedy Low Motion", "greedyl"},
{GST_DEINTERLACE2_VFIR, "Vertical Blur", "vfir"},
{0, NULL, NULL},
};
if (!deinterlace2_method_type) {
deinterlace2_method_type =
g_enum_register_static ("GstDeinterlace2Methods", method_types);
if (!deinterlace2_methods_type) {
deinterlace2_methods_type =
g_enum_register_static ("GstDeinterlace2Methods", methods_types);
}
return deinterlace2_method_type;
return deinterlace2_methods_type;
}
#define GST_TYPE_DEINTERLACE2_FIELDS (gst_deinterlace2_fields_get_type ())
......@@ -141,8 +172,66 @@ static const GstQueryType *gst_deinterlace2_src_query_types (GstPad * pad);
static void gst_deinterlace2_reset (GstDeinterlace2 * object);
GST_BOILERPLATE (GstDeinterlace2, gst_deinterlace2, GstElement,
GST_TYPE_ELEMENT);
static void gst_deinterlace2_child_proxy_interface_init (gpointer g_iface,
gpointer iface_data);
static void
_do_init (GType object_type)
{
const GInterfaceInfo child_proxy_interface_info = {
(GInterfaceInitFunc) gst_deinterlace2_child_proxy_interface_init,
NULL, /* interface_finalize */
NULL /* interface_data */
};
g_type_add_interface_static (object_type, GST_TYPE_CHILD_PROXY,
&child_proxy_interface_info);
}
GST_BOILERPLATE_FULL (GstDeinterlace2, gst_deinterlace2, GstElement,
GST_TYPE_ELEMENT, _do_init);
static void
gst_deinterlace2_set_method (GstDeinterlace2 * object,
GstDeinterlace2Methods method)
{
if (object->method) {
gst_child_proxy_child_removed (GST_OBJECT (object),
GST_OBJECT (object->method));
gst_object_unparent (GST_OBJECT (object->method));
object->method = NULL;
}
switch (method) {
case GST_DEINTERLACE2_TOMSMOCOMP:
object->method = g_object_new (GST_TYPE_DEINTERLACE_TOMSMOCOMP, NULL);
break;
case GST_DEINTERLACE2_GREEDY_H:
object->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_H, NULL);
break;
case GST_DEINTERLACE2_GREEDY_L:
object->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_L, NULL);
break;
case GST_DEINTERLACE2_VFIR:
object->method = g_object_new (GST_TYPE_DEINTERLACE_VFIR, NULL);
break;
default:
GST_WARNING ("Invalid Deinterlacer Method");
return;
}
object->method_id = method;
gst_object_set_name (GST_OBJECT (object->method), "method");
gst_object_set_parent (GST_OBJECT (object->method), GST_OBJECT (object));
gst_child_proxy_child_added (GST_OBJECT (object),
GST_OBJECT (object->method));
/* TODO: if current method requires less fields in the history,
pop the diff from field_history.
*/
}
static void
gst_deinterlace2_base_init (gpointer klass)
......@@ -177,8 +266,9 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
g_param_spec_enum ("method",
"Method",
"Deinterlace Method",
GST_TYPE_DEINTERLACE2_METHOD,
GST_DEINTERLACE2_TOM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
GST_TYPE_DEINTERLACE2_METHODS,
GST_DEINTERLACE2_TOMSMOCOMP,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
);
g_object_class_install_property (gobject_class, ARG_FIELDS,
......@@ -202,6 +292,33 @@ gst_deinterlace2_class_init (GstDeinterlace2Class * klass)
GST_DEBUG_FUNCPTR (gst_deinterlace2_change_state);
}
static GstObject *
gst_deinterlace2_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
guint index)
{
GstDeinterlace2 *self = GST_DEINTERLACE2 (child_proxy);
g_return_val_if_fail (index == 0, NULL);
return gst_object_ref (self->method);
}
static guint
gst_deinterlace2_child_proxy_get_children_count (GstChildProxy * child_proxy)
{
return 1;
}
static void
gst_deinterlace2_child_proxy_interface_init (gpointer g_iface,
gpointer iface_data)
{
GstChildProxyInterface *iface = g_iface;
iface->get_child_by_index = gst_deinterlace2_child_proxy_get_child_by_index;
iface->get_children_count = gst_deinterlace2_child_proxy_get_children_count;
}
static void
gst_deinterlace2_init (GstDeinterlace2 * object, GstDeinterlace2Class * klass)
{
......@@ -231,9 +348,7 @@ gst_deinterlace2_init (GstDeinterlace2 * object, GstDeinterlace2Class * klass)
gst_element_no_more_pads (GST_ELEMENT (object));
object->cpu_feature_flags = oil_cpu_get_flags ();
object->method = dscaler_tomsmocomp_get_method ();
gst_deinterlace2_set_method (object, GST_DEINTERLACE2_TOMSMOCOMP);
object->field_layout = GST_DEINTERLACE2_LAYOUT_AUTO;
object->fields = GST_DEINTERLACE2_ALL;
......@@ -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;
ret = gst_pad_push (object->srcpad, object->out_buf);
object->out_buf = NULL;
if (ret != GST_FLOW_OK)
return ret;
}
GST_BUFFER_DURATION (object->out_buf) / 2;
ret = gst_pad_push (object->srcpad, object->out_buf);
object->out_buf = NULL;
if (ret != GST_FLOW_OK)
return ret;
}
/* no calculation done: remove excess field */
else if (object->field_history[cur_field_idx].flags ==
......@@ -522,7 +614,7 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
gst_buffer_unref (buf);
}
cur_field_idx = object->history_count - object->method->fields_required;
cur_field_idx = object->history_count - fields_required;
/* deinterlace bottom_field */
if ((object->field_history[cur_field_idx].flags == PICTURE_INTERLACED_BOTTOM
......@@ -538,26 +630,24 @@ gst_deinterlace2_chain (GstPad * pad, GstBuffer * buf)
return ret;
/* do magic calculus */
if (object->method->deinterlace_frame != NULL) {
object->method->deinterlace_frame (object);
gst_deinterlace_method_deinterlace_frame (object->method, object);
buf = gst_deinterlace2_pop_history (object);
timestamp = GST_BUFFER_TIMESTAMP (buf);
gst_buffer_unref (buf);
buf = gst_deinterlace2_pop_history (object);
timestamp = GST_BUFFER_TIMESTAMP (buf);
gst_buffer_unref (buf);
GST_BUFFER_TIMESTAMP (object->out_buf) = timestamp;
GST_BUFFER_TIMESTAMP (object->out_buf) = timestamp;
GST_BUFFER_DURATION (object->out_buf) =
GST_SECOND / object->frame_rate_d / object->frame_rate_n;
if (object->fields == GST_DEINTERLACE2_ALL)
GST_BUFFER_DURATION (object->out_buf) =
GST_SECOND / object->frame_rate_d / object->frame_rate_n;
if (object->fields == GST_DEINTERLACE2_ALL)
GST_BUFFER_DURATION (object->out_buf) =
GST_BUFFER_DURATION (object->out_buf) / 2;
GST_BUFFER_DURATION (object->out_buf) / 2;
ret = gst_pad_push (object->srcpad, object->out_buf);
object->out_buf = NULL;
ret = gst_pad_push (object->srcpad, object->out_buf);
object->out_buf = NULL;
if (ret != GST_FLOW_OK)
return ret;
}
if (ret != GST_FLOW_OK)
return ret;
}
/* no calculation done: remove excess field */
else if (object->field_history[cur_field_idx].flags ==
......@@ -757,6 +847,11 @@ gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
if ((peer = gst_pad_get_peer (object->sinkpad))) {
if ((res = gst_pad_query (peer, query))) {
GstClockTime latency;
gint fields_required = 0;
if (object->method)
fields_required =
gst_deinterlace_method_get_fields_required (object->method);
gst_query_parse_latency (query, &live, &min, &max);
......@@ -766,7 +861,7 @@ gst_deinterlace2_src_query (GstPad * pad, GstQuery * query)
/* add our own latency */
latency =
gst_util_uint64_scale (object->method->fields_required *
gst_util_uint64_scale (fields_required *
GST_SECOND, object->frame_rate_d, object->frame_rate_n);
latency /= 2;
......
/*
* GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de>
* Copyright (C) 2008 Sebastian Dröge <slomo@circular-chaos.org>
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -45,29 +45,40 @@ G_BEGIN_DECLS
typedef struct _GstDeinterlace2 GstDeinterlace2;
typedef struct _GstDeinterlace2Class GstDeinterlace2Class;
typedef struct deinterlace_setting_s deinterlace_setting_t;
typedef struct deinterlace_method_s deinterlace_method_t;
#define GST_TYPE_DEINTERLACE_METHOD (gst_deinterlace_method_get_type ())
#define GST_IS_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD))
#define GST_IS_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD))
#define GST_DEINTERLACE_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass))
#define GST_DEINTERLACE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethod))
#define GST_DEINTERLACE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD, GstDeinterlaceMethodClass))
#define GST_DEINTERLACE_METHOD_CAST(obj) ((GstDeinterlaceMethod*)(obj))
typedef void (*deinterlace_frame_t) (GstDeinterlace2 * object);
typedef struct _GstDeinterlaceMethod GstDeinterlaceMethod;
typedef struct _GstDeinterlaceMethodClass GstDeinterlaceMethodClass;
/*
* This structure defines the deinterlacer plugin.
*/
struct deinterlace_method_s
{
int version;
const char *name;
const char *short_name;
int fields_required;
int accelrequired;
int doscalerbob;
int numsettings;
deinterlace_setting_t *settings;
int scanlinemode;
deinterlace_frame_t deinterlace_frame;
const char *description[10];
struct _GstDeinterlaceMethod {
GstObject parent;
};
struct _GstDeinterlaceMethodClass {
GstObjectClass parent_class;
guint fields_required;
guint latency;
gboolean available;
void (*deinterlace_frame) (GstDeinterlaceMethod *self, GstDeinterlace2 * object);
const gchar *name;
const gchar *nick;
};
GType gst_deinterlace_method_get_type (void);
#define MAX_FIELD_HISTORY 10
#define PICTURE_PROGRESSIVE 0
......@@ -75,8 +86,6 @@ struct deinterlace_method_s
#define PICTURE_INTERLACED_TOP 2
#define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP)
typedef void (MEMCPY_FUNC) (void *pOutput, const void *pInput, size_t nSize);
typedef struct
{
/* pointer to the start of data for this field */
......@@ -87,7 +96,7 @@ typedef struct
typedef enum
{
GST_DEINTERLACE2_TOM,
GST_DEINTERLACE2_TOMSMOCOMP,
GST_DEINTERLACE2_GREEDY_H,
GST_DEINTERLACE2_GREEDY_L,
GST_DEINTERLACE2_VFIR
......@@ -115,7 +124,6 @@ struct _GstDeinterlace2
guint history_count;
guint cpu_feature_flags;
GstDeinterlace2FieldLayout field_layout;
guint frame_size;
......@@ -124,7 +132,7 @@ struct _GstDeinterlace2
GstDeinterlace2Fields fields;
GstDeinterlace2Methods method_id;
deinterlace_method_t *method;
GstDeinterlaceMethod *method;
/* The most recent pictures
PictureHistory[0] is always the most recent.
......
......@@ -4,6 +4,8 @@
* Copyright (c) 2000 Tom Barry All rights reserved.
* mmx.h port copyright (c) 2002 Billy Biggs <vektor@dumbterm.net>.
*
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
......@@ -35,6 +37,30 @@
#include "gstdeinterlace2.h"
#include <string.h>
#define GST_TYPE_DEINTERLACE_METHOD_GREEDY_L (gst_deinterlace_method_greedy_l_get_type ())
#define GST_IS_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L))
#define GST_IS_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L))
#define GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass))
#define GST_DEINTERLACE_METHOD_GREEDY_L(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyL))
#define GST_DEINTERLACE_METHOD_GREEDY_L_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_METHOD_GREEDY_L, GstDeinterlaceMethodGreedyLClass))
#define GST_DEINTERLACE_METHOD_GREEDY_L_CAST(obj) ((GstDeinterlaceMethodGreedyL*)(obj))
GType gst_deinterlace_method_greedy_l_get_type (void);
typedef struct
{
GstDeinterlaceMethod parent;
guint max_comb;
} GstDeinterlaceMethodGreedyL;
typedef struct
{
GstDeinterlaceMethodClass parent_class;
void (*scanline) (GstDeinterlaceMethodGreedyL * self, uint8_t * L2,
uint8_t * L1, uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size);
} GstDeinterlaceMethodGreedyLClass;
// This is a simple lightweight DeInterlace method that uses little CPU time
// but gives very good results for low or intermedite motion.
// It defers frames by one field, but that does not seem to produce noticeable
......@@ -47,13 +73,13 @@
// I'd intended this to be part of a larger more elaborate method added to
// Blended Clip but this give too good results for the CPU to ignore here.
static const int GreedyMaxComb = 15;
static inline void
deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
deinterlace_greedy_packed422_scanline_c (GstDeinterlaceMethodGreedyL * self,
uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{
int avg, l2_diff, lp2_diff, max, min, best;
guint max_comb = self->max_comb;
// L2 == m0
// L1 == t1
......@@ -74,13 +100,13 @@ deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
max = MAX (*t1, *b1);
min = MIN (*t1, *b1);
if (max < 256 - GreedyMaxComb)
max += GreedyMaxComb;
if (max < 256 - max_comb)
max += max_comb;
else
max = 255;
if (min > GreedyMaxComb)
min -= GreedyMaxComb;
if (min > max_comb)
min -= max_comb;
else
min = 0;
......@@ -98,22 +124,22 @@ deinterlace_greedy_packed422_scanline_c (uint8_t * m0, uint8_t * t1,
#ifdef HAVE_CPU_I386
#include "mmx.h"
static void
deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
deinterlace_greedy_packed422_scanline_mmx (GstDeinterlaceMethodGreedyL * self,
uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
{
mmx_t MaxComb;
mmx_t ShiftMask;
// How badly do we let it weave? 0-255
MaxComb.ub[0] = GreedyMaxComb;
MaxComb.ub[1] = GreedyMaxComb;
MaxComb.ub[2] = GreedyMaxComb;
MaxComb.ub[3] = GreedyMaxComb;
MaxComb.ub[4] = GreedyMaxComb;
MaxComb.ub[5] = GreedyMaxComb;
MaxComb.ub[6] = GreedyMaxComb;
MaxComb.ub[7] = GreedyMaxComb;
MaxComb.ub[0] = self->max_comb;
MaxComb.ub[1] = self->max_comb;
MaxComb.ub[2] = self->max_comb;
MaxComb.ub[3] = self->max_comb;
MaxComb.ub[4] = self->max_comb;
MaxComb.ub[5] = self->max_comb;
MaxComb.ub[6] = self->max_comb;
MaxComb.ub[7] = self->max_comb;
ShiftMask.ub[0] = 0x7f;
ShiftMask.ub[1] = 0x7f;
......@@ -207,26 +233,28 @@ deinterlace_greedy_packed422_scanline_mmx (uint8_t * m0, uint8_t * t1,
}
emms ();
if (width > 0)
deinterlace_greedy_packed422_scanline_c (m0, t1, b1, m2, output, width);
deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output,
width);
}
#include "sse.h"
static void
deinterlace_greedy_packed422_scanline_mmxext (uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlaceMethodGreedyL *
self, uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2,