mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-29 19:50:40 +00:00
gst/deinterlace2/gstdeinterlace2.*: Add a GstDeinterlaceSimpleMethod subclass of GstDeinterlaceMethod that can be use...
Original commit message from CVS: * gst/deinterlace2/gstdeinterlace2.c: (gst_deinterlace_simple_method_interpolate_scanline), (gst_deinterlace_simple_method_copy_scanline), (gst_deinterlace_simple_method_deinterlace_frame), (gst_deinterlace_simple_method_class_init), (gst_deinterlace_simple_method_init): * gst/deinterlace2/gstdeinterlace2.h: Add a GstDeinterlaceSimpleMethod subclass of GstDeinterlaceMethod that can be used by simple deinterlacing methods. They only have to provide a function for interpolating a scanline or copying a scanline.
This commit is contained in:
parent
8cbe2b9912
commit
163ff0f9a4
3 changed files with 238 additions and 0 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2008-08-02 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
|
||||||
|
* gst/deinterlace2/gstdeinterlace2.c:
|
||||||
|
(gst_deinterlace_simple_method_interpolate_scanline),
|
||||||
|
(gst_deinterlace_simple_method_copy_scanline),
|
||||||
|
(gst_deinterlace_simple_method_deinterlace_frame),
|
||||||
|
(gst_deinterlace_simple_method_class_init),
|
||||||
|
(gst_deinterlace_simple_method_init):
|
||||||
|
* gst/deinterlace2/gstdeinterlace2.h:
|
||||||
|
Add a GstDeinterlaceSimpleMethod subclass of GstDeinterlaceMethod that
|
||||||
|
can be used by simple deinterlacing methods. They only have to provide
|
||||||
|
a function for interpolating a scanline or copying a scanline.
|
||||||
|
|
||||||
2008-08-02 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
2008-08-02 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
|
||||||
* gst/deinterlace2/gstdeinterlace2.c: (gst_deinterlace2_chain):
|
* gst/deinterlace2/gstdeinterlace2.c: (gst_deinterlace2_chain):
|
||||||
|
|
|
@ -89,6 +89,169 @@ gst_deinterlace_method_get_latency (GstDeinterlaceMethod * self)
|
||||||
return klass->latency;
|
return klass->latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GstDeinterlaceSimpleMethod, gst_deinterlace_simple_method,
|
||||||
|
GST_TYPE_DEINTERLACE_METHOD);
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_deinterlace_simple_method_interpolate_scanline (GstDeinterlaceMethod * self,
|
||||||
|
GstDeinterlace2 * parent, guint8 * out,
|
||||||
|
GstDeinterlaceScanlineData * scanlines, gint width)
|
||||||
|
{
|
||||||
|
memcpy (out, scanlines->m1, parent->line_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_deinterlace_simple_method_copy_scanline (GstDeinterlaceMethod * self,
|
||||||
|
GstDeinterlace2 * parent, guint8 * out,
|
||||||
|
GstDeinterlaceScanlineData * scanlines, gint width)
|
||||||
|
{
|
||||||
|
memcpy (out, scanlines->m0, parent->line_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_deinterlace_simple_method_deinterlace_frame (GstDeinterlaceMethod * self,
|
||||||
|
GstDeinterlace2 * parent)
|
||||||
|
{
|
||||||
|
GstDeinterlaceSimpleMethodClass *dsm_class =
|
||||||
|
GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS (self);
|
||||||
|
GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
|
||||||
|
GstDeinterlaceScanlineData scanlines;
|
||||||
|
guint8 *out = GST_BUFFER_DATA (parent->out_buf);
|
||||||
|
guint8 *field0 = NULL, *field1 = NULL, *field2 = NULL, *field3 = NULL;
|
||||||
|
gint cur_field_idx = parent->history_count - dm_class->fields_required;
|
||||||
|
guint cur_field_flags = parent->field_history[cur_field_idx].flags;
|
||||||
|
gint line;
|
||||||
|
|
||||||
|
field0 = GST_BUFFER_DATA (parent->field_history[cur_field_idx].buf);
|
||||||
|
|
||||||
|
g_assert (dm_class->fields_required <= 4);
|
||||||
|
|
||||||
|
if (dm_class->fields_required >= 2)
|
||||||
|
field1 = field0 =
|
||||||
|
GST_BUFFER_DATA (parent->field_history[cur_field_idx + 1].buf);
|
||||||
|
if (dm_class->fields_required >= 3)
|
||||||
|
field1 = field0 =
|
||||||
|
GST_BUFFER_DATA (parent->field_history[cur_field_idx + 2].buf);
|
||||||
|
if (dm_class->fields_required >= 4)
|
||||||
|
field1 = field0 =
|
||||||
|
GST_BUFFER_DATA (parent->field_history[cur_field_idx + 3].buf);
|
||||||
|
|
||||||
|
|
||||||
|
if (cur_field_flags == PICTURE_INTERLACED_BOTTOM) {
|
||||||
|
/* double the first scanline of the bottom field */
|
||||||
|
memcpy (out, field0, parent->line_length);
|
||||||
|
out += parent->output_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (out, field0, parent->line_length);
|
||||||
|
out += parent->output_stride;
|
||||||
|
|
||||||
|
for (line = 2; line <= parent->field_height; line++) {
|
||||||
|
|
||||||
|
memset (&scanlines, 0, sizeof (scanlines));
|
||||||
|
scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
|
||||||
|
|
||||||
|
/* interp. scanline */
|
||||||
|
scanlines.t0 = field0;
|
||||||
|
scanlines.b0 = field0 + parent->field_stride;
|
||||||
|
|
||||||
|
if (field1 != NULL) {
|
||||||
|
scanlines.tt1 = field1;
|
||||||
|
scanlines.m1 = field1 + parent->field_stride;
|
||||||
|
scanlines.bb1 = field1 + parent->field_stride * 2;
|
||||||
|
field1 += parent->field_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field2 != NULL) {
|
||||||
|
scanlines.t2 = field2;
|
||||||
|
scanlines.b2 = field2 + parent->field_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field3 != NULL) {
|
||||||
|
scanlines.tt3 = field3;
|
||||||
|
scanlines.m3 = field3 + parent->field_stride;
|
||||||
|
scanlines.bb3 = field3 + parent->field_stride * 2;
|
||||||
|
field3 += parent->field_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set valid data for corner cases */
|
||||||
|
if (line == 2) {
|
||||||
|
scanlines.tt1 = scanlines.bb1;
|
||||||
|
scanlines.tt3 = scanlines.bb3;
|
||||||
|
} else if (line == parent->field_height) {
|
||||||
|
scanlines.bb1 = scanlines.tt1;
|
||||||
|
scanlines.bb3 = scanlines.tt3;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsm_class->interpolate_scanline (self, parent, out, &scanlines,
|
||||||
|
parent->frame_width);
|
||||||
|
out += parent->output_stride;
|
||||||
|
|
||||||
|
memset (&scanlines, 0, sizeof (scanlines));
|
||||||
|
scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
|
||||||
|
|
||||||
|
/* copy a scanline */
|
||||||
|
scanlines.tt0 = field0;
|
||||||
|
scanlines.m0 = field0 + parent->field_stride;
|
||||||
|
scanlines.bb0 = field0 + parent->field_stride * 2;
|
||||||
|
field0 += parent->field_stride;
|
||||||
|
|
||||||
|
if (field1 != NULL) {
|
||||||
|
scanlines.t1 = field1;
|
||||||
|
scanlines.b1 = field1 + parent->field_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field2 != NULL) {
|
||||||
|
scanlines.tt2 = field2;
|
||||||
|
scanlines.m2 = field2 + parent->field_stride;
|
||||||
|
scanlines.bb2 = field2 + parent->field_stride * 2;
|
||||||
|
field2 += parent->field_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field3 != NULL) {
|
||||||
|
scanlines.t3 = field3;
|
||||||
|
scanlines.b3 = field3 + parent->field_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set valid data for corner cases */
|
||||||
|
if (line == parent->field_height) {
|
||||||
|
scanlines.bb0 = scanlines.tt0;
|
||||||
|
scanlines.b1 = scanlines.t1;
|
||||||
|
scanlines.bb2 = scanlines.tt2;
|
||||||
|
scanlines.b3 = scanlines.t3;
|
||||||
|
}
|
||||||
|
|
||||||
|
dsm_class->copy_scanline (self, parent, out, &scanlines,
|
||||||
|
parent->frame_width);
|
||||||
|
out += parent->output_stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur_field_flags == PICTURE_INTERLACED_TOP) {
|
||||||
|
/* double the last scanline of the top field */
|
||||||
|
memcpy (out, field0, parent->line_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass *
|
||||||
|
klass)
|
||||||
|
{
|
||||||
|
GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass;
|
||||||
|
|
||||||
|
dm_class->deinterlace_frame = gst_deinterlace_simple_method_deinterlace_frame;
|
||||||
|
dm_class->fields_required = 2;
|
||||||
|
|
||||||
|
klass->interpolate_scanline =
|
||||||
|
gst_deinterlace_simple_method_interpolate_scanline;
|
||||||
|
klass->copy_scanline = gst_deinterlace_simple_method_copy_scanline;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_deinterlace_simple_method_init (GstDeinterlaceSimpleMethod * self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#define GST_TYPE_DEINTERLACE2_METHODS (gst_deinterlace2_methods_get_type ())
|
#define GST_TYPE_DEINTERLACE2_METHODS (gst_deinterlace2_methods_get_type ())
|
||||||
static GType
|
static GType
|
||||||
gst_deinterlace2_methods_get_type (void)
|
gst_deinterlace2_methods_get_type (void)
|
||||||
|
|
|
@ -84,6 +84,68 @@ struct _GstDeinterlaceMethodClass {
|
||||||
|
|
||||||
GType gst_deinterlace_method_get_type (void);
|
GType gst_deinterlace_method_get_type (void);
|
||||||
|
|
||||||
|
#define GST_TYPE_DEINTERLACE_SIMPLE_METHOD (gst_deinterlace_simple_method_get_type ())
|
||||||
|
#define GST_IS_DEINTERLACE_SIMPLE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD))
|
||||||
|
#define GST_IS_DEINTERLACE_SIMPLE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DEINTERLACE_SIMPLE_METHOD))
|
||||||
|
#define GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethodClass))
|
||||||
|
#define GST_DEINTERLACE_SIMPLE_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethod))
|
||||||
|
#define GST_DEINTERLACE_SIMPLE_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DEINTERLACE_SIMPLE_METHOD, GstDeinterlaceSimpleMethodClass))
|
||||||
|
#define GST_DEINTERLACE_SIMPLE_METHOD_CAST(obj) ((GstDeinterlaceSimpleMethod*)(obj))
|
||||||
|
|
||||||
|
typedef struct _GstDeinterlaceSimpleMethod GstDeinterlaceSimpleMethod;
|
||||||
|
typedef struct _GstDeinterlaceSimpleMethodClass GstDeinterlaceSimpleMethodClass;
|
||||||
|
typedef struct _GstDeinterlaceScanlineData GstDeinterlaceScanlineData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This structure defines the simple deinterlacer plugin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _GstDeinterlaceScanlineData {
|
||||||
|
guint8 *tt0, *t0, *m0, *b0, *bb0;
|
||||||
|
guint8 *tt1, *t1, *m1, *b1, *bb1;
|
||||||
|
guint8 *tt2, *t2, *m2, *b2, *bb2;
|
||||||
|
guint8 *tt3, *t3, *m3, *b3, *bb3;
|
||||||
|
gboolean bottom_field;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For interpolate_scanline the input is:
|
||||||
|
*
|
||||||
|
* | t-3 t-2 t-1 t
|
||||||
|
* | Field 3 | Field 2 | Field 1 | Field 0 |
|
||||||
|
* | TT3 | | TT1 | |
|
||||||
|
* | | T2 | | T0 |
|
||||||
|
* | M3 | | M1 | |
|
||||||
|
* | | B2 | | B0 |
|
||||||
|
* | BB3 | | BB1 | |
|
||||||
|
*
|
||||||
|
* For copy_scanline the input is:
|
||||||
|
*
|
||||||
|
* | t-3 t-2 t-1 t
|
||||||
|
* | Field 3 | Field 2 | Field 1 | Field 0 |
|
||||||
|
* | | TT2 | | TT0 |
|
||||||
|
* | T3 | | T1 | |
|
||||||
|
* | | M2 | | M0 |
|
||||||
|
* | B3 | | B1 | |
|
||||||
|
* | | BB2 | | BB0 |
|
||||||
|
*
|
||||||
|
* All other values are NULL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _GstDeinterlaceSimpleMethod {
|
||||||
|
GstDeinterlaceMethod parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GstDeinterlaceSimpleMethodClass {
|
||||||
|
GstDeinterlaceMethodClass parent_class;
|
||||||
|
|
||||||
|
void (*interpolate_scanline) (GstDeinterlaceMethod *self, GstDeinterlace2 * parent, guint8 *out, GstDeinterlaceScanlineData *scanlines, gint width);
|
||||||
|
void (*copy_scanline) (GstDeinterlaceMethod *self, GstDeinterlace2 * parent, guint8 *out, GstDeinterlaceScanlineData *scanlines, gint width);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gst_deinterlace_simple_method_get_type (void);
|
||||||
|
|
||||||
|
|
||||||
#define MAX_FIELD_HISTORY 10
|
#define MAX_FIELD_HISTORY 10
|
||||||
|
|
||||||
#define PICTURE_PROGRESSIVE 0
|
#define PICTURE_PROGRESSIVE 0
|
||||||
|
|
Loading…
Reference in a new issue