deinterlace: Refactor deinterlacing as preparation for supporting more color formats

This commit is contained in:
Sebastian Dröge 2010-04-21 17:00:05 +02:00
parent e2eb012a41
commit 3dc7215492
15 changed files with 839 additions and 590 deletions

View file

@ -2,10 +2,10 @@ plugin_LTLIBRARIES = libgstdeinterlace.la
libgstdeinterlace_la_SOURCES = \
gstdeinterlace.c \
tvtime/tomsmocomp.c \
tvtime/greedy.c \
tvtime/greedyh.c \
tvtime/vfir.c \
tvtime/tomsmocomp.c \
tvtime/weavetff.c \
tvtime/weavebff.c \
tvtime/weave.c \

View file

@ -1,7 +1,7 @@
/*
* GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de>
* Copyright (C) 2008-2009 Sebastian Dröge <slomo@collabora.co.uk>
* Copyright (C) 2008-2010 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
@ -70,25 +70,104 @@ enum
G_DEFINE_TYPE (GstDeinterlaceMethod, gst_deinterlace_method, GST_TYPE_OBJECT);
static gboolean
gst_deinterlace_method_supported (GType type, GstVideoFormat format, gint width,
gint height)
{
GstDeinterlaceMethodClass *klass =
GST_DEINTERLACE_METHOD_CLASS (g_type_class_ref (type));
gboolean ret;
if (format == GST_VIDEO_FORMAT_UNKNOWN)
ret = TRUE;
else
ret = klass->supported (klass, format, width, height);
g_type_class_unref (klass);
return ret;
}
static gboolean
gst_deinterlace_method_supported_impl (GstDeinterlaceMethodClass * klass,
GstVideoFormat format, gint width, gint height)
{
switch (format) {
case GST_VIDEO_FORMAT_YUY2:
return (klass->deinterlace_frame_yuy2 != NULL);
case GST_VIDEO_FORMAT_YVYU:
return (klass->deinterlace_frame_yvyu != NULL);
default:
return FALSE;
}
}
static void
gst_deinterlace_method_setup (GstDeinterlaceMethod * self,
GstVideoFormat format, gint width, gint height)
{
GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
klass->setup (self, format, width, height);
}
static void
gst_deinterlace_method_setup_impl (GstDeinterlaceMethod * self,
GstVideoFormat format, gint width, gint height)
{
gint i;
GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
self->format = format;
self->frame_width = width;
self->frame_height = height;
self->deinterlace_frame = NULL;
if (format == GST_VIDEO_FORMAT_UNKNOWN)
return;
for (i = 0; i < 4; i++) {
self->width[i] = gst_video_format_get_component_width (format, i, width);
self->height[i] = gst_video_format_get_component_height (format, i, height);
self->offset[i] =
gst_video_format_get_component_offset (format, i, width, height);
self->row_stride[i] = gst_video_format_get_row_stride (format, i, width);
self->pixel_stride[i] = gst_video_format_get_pixel_stride (format, i);
}
switch (format) {
case GST_VIDEO_FORMAT_YUY2:
self->deinterlace_frame = klass->deinterlace_frame_yuy2;
break;
case GST_VIDEO_FORMAT_YVYU:
self->deinterlace_frame = klass->deinterlace_frame_yvyu;
break;
default:
self->deinterlace_frame = NULL;
break;
}
}
static void
gst_deinterlace_method_class_init (GstDeinterlaceMethodClass * klass)
{
klass->setup = gst_deinterlace_method_setup_impl;
klass->supported = gst_deinterlace_method_supported_impl;
}
static void
gst_deinterlace_method_init (GstDeinterlaceMethod * self)
{
self->format = GST_VIDEO_FORMAT_UNKNOWN;
}
static void
gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self,
GstDeinterlace * parent, GstBuffer * outbuf)
const GstDeinterlaceField * history, guint history_count,
GstBuffer * outbuf)
{
GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
klass->deinterlace_frame (self, parent, outbuf);
g_assert (self->deinterlace_frame != NULL);
self->deinterlace_frame (self, history, history_count, outbuf);
}
static gint
@ -107,144 +186,215 @@ gst_deinterlace_method_get_latency (GstDeinterlaceMethod * self)
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,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
static gboolean
gst_deinterlace_simple_method_supported (GstDeinterlaceMethodClass * mklass,
GstVideoFormat format, gint width, gint height)
{
oil_memcpy (out, scanlines->m1, parent->row_stride);
GstDeinterlaceSimpleMethodClass *klass =
GST_DEINTERLACE_SIMPLE_METHOD_CLASS (mklass);
if (!GST_DEINTERLACE_METHOD_CLASS
(gst_deinterlace_simple_method_parent_class)->supported (mklass, format,
width, height))
return FALSE;
switch (format) {
case GST_VIDEO_FORMAT_YUY2:
return (klass->interpolate_scanline_yuy2 != NULL
&& klass->copy_scanline_yuy2 != NULL);
case GST_VIDEO_FORMAT_YVYU:
return (klass->interpolate_scanline_yvyu != NULL
&& klass->copy_scanline_yvyu != NULL);
default:
return FALSE;
}
}
static void
gst_deinterlace_simple_method_copy_scanline (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
gst_deinterlace_simple_method_interpolate_scanline_packed
(GstDeinterlaceSimpleMethod * self, guint8 * out,
const GstDeinterlaceScanlineData * scanlines)
{
oil_memcpy (out, scanlines->m0, parent->row_stride);
oil_memcpy (out, scanlines->m1, self->parent.row_stride[0]);
}
static void
gst_deinterlace_simple_method_deinterlace_frame (GstDeinterlaceMethod * self,
GstDeinterlace * parent, GstBuffer * outbuf)
gst_deinterlace_simple_method_copy_scanline_packed (GstDeinterlaceSimpleMethod *
self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
GstDeinterlaceSimpleMethodClass *dsm_class =
GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS (self);
oil_memcpy (out, scanlines->m0, self->parent.row_stride[0]);
}
static void
gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod *
method, const GstDeinterlaceField * history, guint history_count,
GstBuffer * outbuf)
{
GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
GstDeinterlaceScanlineData scanlines;
guint8 *out = GST_BUFFER_DATA (outbuf);
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 cur_field_idx = history_count - dm_class->fields_required;
guint cur_field_flags = history[cur_field_idx].flags;
gint line;
gint field_height = self->parent.frame_height / 2;
gint row_stride = self->parent.row_stride[0];
gint field_stride = self->parent.row_stride[0] * 2;
field0 = GST_BUFFER_DATA (parent->field_history[cur_field_idx].buf);
g_assert (self->interpolate_scanline_packed != NULL);
g_assert (self->copy_scanline_packed != NULL);
field0 = GST_BUFFER_DATA (history[cur_field_idx].buf);
if (history[cur_field_idx].flags & PICTURE_INTERLACED_BOTTOM)
field0 += row_stride;
g_return_if_fail (dm_class->fields_required <= 4);
if (dm_class->fields_required >= 2)
field1 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 1].buf);
if (dm_class->fields_required >= 3)
field2 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 2].buf);
if (dm_class->fields_required >= 4)
field3 = GST_BUFFER_DATA (parent->field_history[cur_field_idx + 3].buf);
if (dm_class->fields_required >= 2) {
field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf);
if (history[cur_field_idx + 1].flags & PICTURE_INTERLACED_BOTTOM)
field1 += row_stride;
}
if (dm_class->fields_required >= 3) {
field2 = GST_BUFFER_DATA (history[cur_field_idx + 2].buf);
if (history[cur_field_idx + 2].flags & PICTURE_INTERLACED_BOTTOM)
field2 += row_stride;
}
if (dm_class->fields_required >= 4) {
field3 = GST_BUFFER_DATA (history[cur_field_idx + 3].buf);
if (history[cur_field_idx + 3].flags & PICTURE_INTERLACED_BOTTOM)
field3 += row_stride;
}
if (cur_field_flags == PICTURE_INTERLACED_BOTTOM) {
/* double the first scanline of the bottom field */
oil_memcpy (out, field0, parent->row_stride);
out += parent->row_stride;
oil_memcpy (out, field0, row_stride);
out += row_stride;
}
oil_memcpy (out, field0, parent->row_stride);
out += parent->row_stride;
oil_memcpy (out, field0, row_stride);
out += row_stride;
for (line = 2; line <= parent->field_height; line++) {
for (line = 2; line <= 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;
scanlines.b0 = field0 + 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;
scanlines.m1 = field1 + field_stride;
scanlines.bb1 = field1 + field_stride * 2;
field1 += field_stride;
}
if (field2 != NULL) {
scanlines.t2 = field2;
scanlines.b2 = field2 + parent->field_stride;
scanlines.b2 = field2 + 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;
scanlines.m3 = field3 + field_stride;
scanlines.bb3 = field3 + field_stride * 2;
field3 += 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) {
} else if (line == field_height) {
scanlines.bb1 = scanlines.tt1;
scanlines.bb3 = scanlines.tt3;
}
dsm_class->interpolate_scanline (self, parent, out, &scanlines,
parent->frame_width);
out += parent->row_stride;
self->interpolate_scanline_packed (self, out, &scanlines);
out += row_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;
scanlines.m0 = field0 + field_stride;
scanlines.bb0 = field0 + field_stride * 2;
field0 += field_stride;
if (field1 != NULL) {
scanlines.t1 = field1;
scanlines.b1 = field1 + parent->field_stride;
scanlines.b1 = field1 + 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;
scanlines.m2 = field2 + field_stride;
scanlines.bb2 = field2 + field_stride * 2;
field2 += field_stride;
}
if (field3 != NULL) {
scanlines.t3 = field3;
scanlines.b3 = field3 + parent->field_stride;
scanlines.b3 = field3 + field_stride;
}
/* set valid data for corner cases */
if (line == parent->field_height) {
if (line == 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->row_stride;
self->copy_scanline_packed (self, out, &scanlines);
out += row_stride;
}
if (cur_field_flags == PICTURE_INTERLACED_TOP) {
/* double the last scanline of the top field */
oil_memcpy (out, field0, parent->row_stride);
oil_memcpy (out, field0, row_stride);
}
}
static void
gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method,
GstVideoFormat format, gint width, gint height)
{
GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
GstDeinterlaceSimpleMethodClass *klass =
GST_DEINTERLACE_SIMPLE_METHOD_GET_CLASS (self);
GST_DEINTERLACE_METHOD_CLASS
(gst_deinterlace_simple_method_parent_class)->setup (method, format,
width, height);
self->interpolate_scanline_packed = NULL;
self->copy_scanline_packed = NULL;
if (format == GST_VIDEO_FORMAT_UNKNOWN)
return;
switch (format) {
case GST_VIDEO_FORMAT_YUY2:
self->interpolate_scanline_packed = klass->interpolate_scanline_yuy2;
self->copy_scanline_packed = klass->copy_scanline_yuy2;
break;
case GST_VIDEO_FORMAT_YVYU:
self->interpolate_scanline_packed = klass->interpolate_scanline_yvyu;
self->copy_scanline_packed = klass->copy_scanline_yvyu;
break;
default:
break;
}
}
@ -254,12 +404,22 @@ gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass *
{
GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass;
dm_class->deinterlace_frame = gst_deinterlace_simple_method_deinterlace_frame;
dm_class->deinterlace_frame_yuy2 =
gst_deinterlace_simple_method_deinterlace_frame_packed;
dm_class->deinterlace_frame_yvyu =
gst_deinterlace_simple_method_deinterlace_frame_packed;
dm_class->fields_required = 2;
dm_class->setup = gst_deinterlace_simple_method_setup;
dm_class->supported = gst_deinterlace_simple_method_supported;
klass->interpolate_scanline =
gst_deinterlace_simple_method_interpolate_scanline;
klass->copy_scanline = gst_deinterlace_simple_method_copy_scanline;
klass->interpolate_scanline_yuy2 =
gst_deinterlace_simple_method_interpolate_scanline_packed;
klass->copy_scanline_yuy2 =
gst_deinterlace_simple_method_copy_scanline_packed;
klass->interpolate_scanline_yvyu =
gst_deinterlace_simple_method_interpolate_scanline_packed;
klass->copy_scanline_yvyu =
gst_deinterlace_simple_method_copy_scanline_packed;
}
static void
@ -417,59 +577,81 @@ _do_init (GType object_type)
GST_BOILERPLATE_FULL (GstDeinterlace, gst_deinterlace, GstElement,
GST_TYPE_ELEMENT, _do_init);
static const struct
{
GType (*get_type) (void);
} _method_types[] = {
{
gst_deinterlace_method_tomsmocomp_get_type}, {
gst_deinterlace_method_greedy_h_get_type}, {
gst_deinterlace_method_greedy_l_get_type}, {
gst_deinterlace_method_vfir_get_type}, {
gst_deinterlace_method_linear_get_type}, {
gst_deinterlace_method_linear_blend_get_type}, {
gst_deinterlace_method_scaler_bob_get_type}, {
gst_deinterlace_method_weave_get_type}, {
gst_deinterlace_method_weave_tff_get_type}, {
gst_deinterlace_method_weave_bff_get_type}
};
static void
gst_deinterlace_set_method (GstDeinterlace * self, GstDeinterlaceMethods method)
{
GType method_type;
GST_DEBUG_OBJECT (self, "Setting new method %d", method);
if (self->method) {
if (self->method_id == method &&
gst_deinterlace_method_supported (G_TYPE_FROM_INSTANCE (self->method),
self->format, self->width, self->height)) {
GST_DEBUG_OBJECT (self, "Reusing current method");
return;
}
gst_child_proxy_child_removed (GST_OBJECT (self),
GST_OBJECT (self->method));
gst_object_unparent (GST_OBJECT (self->method));
self->method = NULL;
}
switch (method) {
case GST_DEINTERLACE_TOMSMOCOMP:
self->method = g_object_new (GST_TYPE_DEINTERLACE_TOMSMOCOMP, NULL);
break;
case GST_DEINTERLACE_GREEDY_H:
self->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_H, NULL);
break;
case GST_DEINTERLACE_GREEDY_L:
self->method = g_object_new (GST_TYPE_DEINTERLACE_GREEDY_L, NULL);
break;
case GST_DEINTERLACE_VFIR:
self->method = g_object_new (GST_TYPE_DEINTERLACE_VFIR, NULL);
break;
case GST_DEINTERLACE_LINEAR:
self->method = g_object_new (GST_TYPE_DEINTERLACE_LINEAR, NULL);
break;
case GST_DEINTERLACE_LINEAR_BLEND:
self->method = g_object_new (GST_TYPE_DEINTERLACE_LINEAR_BLEND, NULL);
break;
case GST_DEINTERLACE_SCALER_BOB:
self->method = g_object_new (GST_TYPE_DEINTERLACE_SCALER_BOB, NULL);
break;
case GST_DEINTERLACE_WEAVE:
self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE, NULL);
break;
case GST_DEINTERLACE_WEAVE_TFF:
self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE_TFF, NULL);
break;
case GST_DEINTERLACE_WEAVE_BFF:
self->method = g_object_new (GST_TYPE_DEINTERLACE_WEAVE_BFF, NULL);
break;
default:
GST_WARNING_OBJECT (self, "Invalid Deinterlacer Method");
return;
method_type =
_method_types[method].get_type !=
NULL ? _method_types[method].get_type () : G_TYPE_INVALID;
if (method_type == G_TYPE_INVALID
|| !gst_deinterlace_method_supported (method_type, self->format,
self->width, self->height)) {
GType tmp;
gint i;
method_type = G_TYPE_INVALID;
GST_WARNING_OBJECT (self, "Method doesn't support requested format");
for (i = 0; i < G_N_ELEMENTS (_method_types); i++) {
if (_method_types[i].get_type == NULL)
continue;
tmp = _method_types[i].get_type ();
if (gst_deinterlace_method_supported (tmp, self->format, self->width,
self->height)) {
GST_DEBUG_OBJECT (self, "Using method %d", i);
method_type = tmp;
break;
}
}
/* If we get here we must have invalid caps! */
g_assert (method_type != G_TYPE_INVALID);
}
self->method = g_object_new (method_type, NULL);
self->method_id = method;
gst_object_set_name (GST_OBJECT (self->method), "method");
gst_object_set_parent (GST_OBJECT (self->method), GST_OBJECT (self));
gst_child_proxy_child_added (GST_OBJECT (self), GST_OBJECT (self->method));
if (self->method)
gst_deinterlace_method_setup (self->method, self->format, self->width,
self->height);
}
static gboolean
@ -757,7 +939,7 @@ gst_deinterlace_reset_history (GstDeinterlace * self)
}
}
memset (self->field_history, 0,
GST_DEINTERLACE_MAX_FIELD_HISTORY * sizeof (GstPicture));
GST_DEINTERLACE_MAX_FIELD_HISTORY * sizeof (GstDeinterlaceField));
self->history_count = 0;
if (self->last_buffer)
@ -770,13 +952,11 @@ gst_deinterlace_reset (GstDeinterlace * self)
{
GST_DEBUG_OBJECT (self, "Resetting internal state");
self->row_stride = 0;
self->frame_width = 0;
self->frame_height = 0;
self->frame_rate_n = 0;
self->frame_rate_d = 0;
self->field_height = 0;
self->field_stride = 0;
self->format = GST_VIDEO_FORMAT_UNKNOWN;
self->width = 0;
self->height = 0;
self->frame_size = 0;
self->fps_n = self->fps_d = 0;
gst_segment_init (&self->segment, GST_FORMAT_TIME);
@ -948,13 +1128,11 @@ gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer)
GST_DEBUG_OBJECT (self, "Top field first");
field1 = gst_buffer_ref (buffer);
field1_flags = PICTURE_INTERLACED_TOP;
field2 = gst_buffer_create_sub (buffer, self->row_stride,
GST_BUFFER_SIZE (buffer) - self->row_stride);
field2 = gst_buffer_ref (buffer);
field2_flags = PICTURE_INTERLACED_BOTTOM;
} else {
GST_DEBUG_OBJECT (self, "Bottom field first");
field1 = gst_buffer_create_sub (buffer, self->row_stride,
GST_BUFFER_SIZE (buffer) - self->row_stride);
field1 = gst_buffer_ref (buffer);
field1_flags = PICTURE_INTERLACED_BOTTOM;
field2 = gst_buffer_ref (buffer);
field2_flags = PICTURE_INTERLACED_TOP;
@ -1172,7 +1350,8 @@ gst_deinterlace_chain (GstPad * pad, GstBuffer * buf)
ret = GST_FLOW_OK;
} else {
/* do magic calculus */
gst_deinterlace_method_deinterlace_frame (self->method, self, outbuf);
gst_deinterlace_method_deinterlace_frame (self->method,
self->field_history, self->history_count, outbuf);
gst_buffer_unref (gst_deinterlace_pop_history (self));
@ -1249,7 +1428,8 @@ gst_deinterlace_chain (GstPad * pad, GstBuffer * buf)
ret = GST_FLOW_OK;
} else {
/* do magic calculus */
gst_deinterlace_method_deinterlace_frame (self->method, self, outbuf);
gst_deinterlace_method_deinterlace_frame (self->method,
self->field_history, self->history_count, outbuf);
gst_buffer_unref (gst_deinterlace_pop_history (self));
@ -1476,33 +1656,23 @@ gst_deinterlace_setcaps (GstPad * pad, GstCaps * caps)
gboolean res = TRUE;
GstDeinterlace *self = GST_DEINTERLACE (gst_pad_get_parent (pad));
GstPad *otherpad;
GstStructure *structure;
GstVideoFormat fmt;
guint32 fourcc;
GstCaps *othercaps;
otherpad = (pad == self->srcpad) ? self->sinkpad : self->srcpad;
structure = gst_caps_get_structure (caps, 0);
res = gst_structure_get_int (structure, "width", &self->frame_width);
res &= gst_structure_get_int (structure, "height", &self->frame_height);
res &=
gst_structure_get_fraction (structure, "framerate", &self->frame_rate_n,
&self->frame_rate_d);
res &= gst_structure_get_fourcc (structure, "format", &fourcc);
if (pad == self->sinkpad) {
res =
gst_video_format_parse_caps (caps, &self->format, &self->width,
&self->height);
res &= gst_video_parse_caps_framerate (caps, &self->fps_n, &self->fps_d);
if (pad == self->sinkpad)
res &= gst_video_format_parse_caps_interlaced (caps, &self->interlaced);
} else {
res &= gst_video_format_parse_caps_interlaced (caps, &self->src_interlaced);
}
if (!res)
goto invalid_caps;
if ((self->interlaced || self->mode == GST_DEINTERLACE_MODE_INTERLACED) &&
self->fields == GST_DEINTERLACE_ALL
&& self->mode != GST_DEINTERLACE_MODE_DISABLED) {
gint fps_n = self->frame_rate_n, fps_d = self->frame_rate_d;
gint fps_n = self->fps_n, fps_d = self->fps_d;
if (!gst_fraction_double (&fps_n, &fps_d, otherpad != self->srcpad))
goto invalid_caps;
@ -1516,39 +1686,22 @@ gst_deinterlace_setcaps (GstPad * pad, GstCaps * caps)
}
if (otherpad == self->srcpad && self->mode != GST_DEINTERLACE_MODE_DISABLED) {
GstStructure *s;
othercaps = gst_caps_make_writable (othercaps);
s = gst_caps_get_structure (othercaps, 0);
gst_structure_remove_field (s, "interlaced");
gst_caps_set_simple (othercaps, "interlaced", G_TYPE_BOOLEAN, FALSE, NULL);
}
if (!gst_pad_set_caps (otherpad, othercaps))
goto caps_not_accepted;
self->field_height = self->frame_height / 2;
fmt = gst_video_format_from_fourcc (fourcc);
/* TODO: only true if fields are subbuffers of interlaced frames,
change when the buffer-fields concept has landed */
self->field_stride =
gst_video_format_get_row_stride (fmt, 0, self->frame_width) * 2;
/* in bytes */
self->row_stride =
gst_video_format_get_row_stride (fmt, 0, self->frame_width);
self->frame_size =
gst_video_format_get_size (fmt, self->frame_width, self->frame_height);
gst_video_format_get_size (self->format, self->width, self->height);
if (self->fields == GST_DEINTERLACE_ALL && otherpad == self->srcpad)
self->field_duration =
gst_util_uint64_scale (GST_SECOND, self->frame_rate_d,
self->frame_rate_n);
gst_util_uint64_scale (GST_SECOND, self->fps_d, self->fps_n);
else
self->field_duration =
gst_util_uint64_scale (GST_SECOND, self->frame_rate_d,
2 * self->frame_rate_n);
gst_util_uint64_scale (GST_SECOND, self->fps_d, 2 * self->fps_n);
if (pad == self->sinkpad) {
gst_caps_replace (&self->sink_caps, caps);
@ -1558,6 +1711,10 @@ gst_deinterlace_setcaps (GstPad * pad, GstCaps * caps)
gst_caps_replace (&self->sink_caps, othercaps);
}
gst_deinterlace_set_method (self, self->method_id);
gst_deinterlace_method_setup (self->method, self->format, self->width,
self->height);
GST_DEBUG_OBJECT (pad, "Set caps: %" GST_PTR_FORMAT, caps);
GST_DEBUG_OBJECT (pad, "Other caps: %" GST_PTR_FORMAT, othercaps);

View file

@ -1,7 +1,7 @@
/*
* GStreamer
* Copyright (C) 2005 Martin Eikermann <meiker@upb.de>
* Copyright (C) 2008-2009 Sebastian Dröge <slomo@collabora.co.uk>
* Copyright (C) 2008-2010 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
@ -24,6 +24,7 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <liboil/liboil.h>
#include <liboil/liboilcpu.h>
#include <liboil/liboilfunction.h>
@ -61,12 +62,39 @@ typedef struct _GstDeinterlaceClass GstDeinterlaceClass;
typedef struct _GstDeinterlaceMethod GstDeinterlaceMethod;
typedef struct _GstDeinterlaceMethodClass GstDeinterlaceMethodClass;
#define PICTURE_PROGRESSIVE 0
#define PICTURE_INTERLACED_BOTTOM 1
#define PICTURE_INTERLACED_TOP 2
#define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP)
typedef struct
{
/* pointer to the start of data for this field */
GstBuffer *buf;
/* see PICTURE_ flags in *.c */
guint flags;
} GstDeinterlaceField;
/*
* This structure defines the deinterlacer plugin.
*/
typedef void (*GstDeinterlaceMethodDeinterlaceFunction) (GstDeinterlaceMethod *self, const GstDeinterlaceField *history, guint history_count, GstBuffer *outbuf);
struct _GstDeinterlaceMethod {
GstObject parent;
GstVideoFormat format;
gint frame_width, frame_height;
gint width[4];
gint height[4];
gint offset[4];
gint row_stride[4];
gint pixel_stride[4];
GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame;
};
struct _GstDeinterlaceMethodClass {
@ -74,7 +102,12 @@ struct _GstDeinterlaceMethodClass {
guint fields_required;
guint latency;
void (*deinterlace_frame) (GstDeinterlaceMethod *self, GstDeinterlace * parent, GstBuffer *outbuf);
gboolean (*supported) (GstDeinterlaceMethodClass *klass, GstVideoFormat format, gint width, gint height);
void (*setup) (GstDeinterlaceMethod *self, GstVideoFormat format, gint width, gint height);
GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_yuy2;
GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_yvyu;
const gchar *name;
const gchar *nick;
@ -99,10 +132,10 @@ typedef struct _GstDeinterlaceScanlineData GstDeinterlaceScanlineData;
*/
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;
const guint8 *tt0, *t0, *m0, *b0, *bb0;
const guint8 *tt1, *t1, *m1, *b1, *bb1;
const guint8 *tt2, *t2, *m2, *b2, *bb2;
const guint8 *tt3, *t3, *m3, *b3, *bb3;
gboolean bottom_field;
};
@ -130,35 +163,29 @@ struct _GstDeinterlaceScanlineData {
* All other values are NULL.
*/
typedef void (*GstDeinterlaceSimpleMethodPackedFunction) (GstDeinterlaceSimpleMethod *self, guint8 *out, const GstDeinterlaceScanlineData *scanlines);
struct _GstDeinterlaceSimpleMethod {
GstDeinterlaceMethod parent;
GstDeinterlaceSimpleMethodPackedFunction interpolate_scanline_packed;
GstDeinterlaceSimpleMethodPackedFunction copy_scanline_packed;
};
struct _GstDeinterlaceSimpleMethodClass {
GstDeinterlaceMethodClass parent_class;
void (*interpolate_scanline) (GstDeinterlaceMethod *self, GstDeinterlace * parent, guint8 *out, GstDeinterlaceScanlineData *scanlines, gint width);
void (*copy_scanline) (GstDeinterlaceMethod *self, GstDeinterlace * parent, guint8 *out, GstDeinterlaceScanlineData *scanlines, gint width);
/* Packed formats */
GstDeinterlaceSimpleMethodPackedFunction interpolate_scanline_yuy2;
GstDeinterlaceSimpleMethodPackedFunction copy_scanline_yuy2;
GstDeinterlaceSimpleMethodPackedFunction interpolate_scanline_yvyu;
GstDeinterlaceSimpleMethodPackedFunction copy_scanline_yvyu;
};
GType gst_deinterlace_simple_method_get_type (void);
#define GST_DEINTERLACE_MAX_FIELD_HISTORY 10
#define PICTURE_PROGRESSIVE 0
#define PICTURE_INTERLACED_BOTTOM 1
#define PICTURE_INTERLACED_TOP 2
#define PICTURE_INTERLACED_MASK (PICTURE_INTERLACED_BOTTOM | PICTURE_INTERLACED_TOP)
typedef struct
{
/* pointer to the start of data for this field */
GstBuffer *buf;
/* see PICTURE_ flags in *.c */
guint flags;
} GstPicture;
typedef enum
{
GST_DEINTERLACE_TOMSMOCOMP,
@ -210,42 +237,20 @@ struct _GstDeinterlace
GstDeinterlaceMethods method_id;
GstDeinterlaceMethod *method;
guint frame_size;
gint frame_rate_n, frame_rate_d;
gboolean interlaced;
gboolean src_interlaced;
GstVideoFormat format;
gint width, height; /* frame width & height */
guint frame_size; /* frame size in bytes */
gint fps_n, fps_d; /* frame rate */
gboolean interlaced; /* is input interlaced? */
/* Number of bytes of actual data in each scanline. May be less than
OverlayPitch since the overlay's scanlines might have alignment
requirements. Generally equal to FrameWidth * 2.
*/
guint row_stride;
/* Number of pixels in each scanline. */
gint frame_width;
/* Number of scanlines per frame. */
gint frame_height;
/* Number of scanlines per field. FrameHeight / 2, mostly for
cleanliness so we don't have to keep dividing FrameHeight by 2.
*/
gint field_height;
/* distance between lines in image
need not match the pixel width
*/
guint field_stride;
/* Duration of one field */
GstClockTime field_duration;
GstClockTime field_duration; /* Duration of one field */
/* The most recent pictures
PictureHistory[0] is always the most recent.
Pointers are NULL if the picture in question isn't valid, e.g. because
the program just started or a picture was skipped.
*/
GstPicture field_history[GST_DEINTERLACE_MAX_FIELD_HISTORY];
GstDeinterlaceField field_history[GST_DEINTERLACE_MAX_FIELD_HISTORY];
guint history_count;
/* Set to TRUE if we're in still frame mode,
@ -278,4 +283,5 @@ struct _GstDeinterlaceClass
GType gst_deinterlace_get_type (void);
G_END_DECLS
#endif /* __GST_DEINTERLACE_H__ */

View file

@ -4,7 +4,7 @@
* 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>
* Copyright (C) 2008,2010 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
@ -32,8 +32,6 @@
# include "config.h"
#endif
#include "_stdint.h"
#include "gstdeinterlace.h"
#include <string.h>
@ -57,8 +55,9 @@ typedef struct
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);
void (*scanline) (GstDeinterlaceMethodGreedyL * self, const guint8 * L2,
const guint8 * L1, const guint8 * L3, const guint8 * L2P, guint8 * Dest,
gint width);
} GstDeinterlaceMethodGreedyLClass;
// This is a simple lightweight DeInterlace method that uses little CPU time
@ -74,11 +73,11 @@ typedef struct
// Blended Clip but this give too good results for the CPU to ignore here.
static inline void
deinterlace_greedy_packed422_scanline_c (GstDeinterlaceMethodGreedyL * self,
uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
deinterlace_greedy_scanline_c (GstDeinterlaceMethodGreedyL * self,
const guint8 * m0, const guint8 * t1,
const guint8 * b1, const guint8 * m2, guint8 * output, gint width)
{
int avg, l2_diff, lp2_diff, max, min, best;
gint avg, l2_diff, lp2_diff, max, min, best;
guint max_comb = self->max_comb;
// L2 == m0
@ -124,9 +123,9 @@ deinterlace_greedy_packed422_scanline_c (GstDeinterlaceMethodGreedyL * self,
#ifdef BUILD_X86_ASM
#include "mmx.h"
static void
deinterlace_greedy_packed422_scanline_mmx (GstDeinterlaceMethodGreedyL * self,
uint8_t * m0, uint8_t * t1,
uint8_t * b1, uint8_t * m2, uint8_t * output, int width)
deinterlace_greedy_scanline_mmx (GstDeinterlaceMethodGreedyL * self,
const guint8 * m0, const guint8 * t1,
const guint8 * b1, const guint8 * m2, guint8 * output, gint width)
{
mmx_t MaxComb;
mmx_t ShiftMask;
@ -233,16 +232,15 @@ deinterlace_greedy_packed422_scanline_mmx (GstDeinterlaceMethodGreedyL * self,
}
emms ();
if (width > 0)
deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output,
width);
deinterlace_greedy_scanline_c (self, m0, t1, b1, m2, output, width);
}
#include "sse.h"
static void
deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlaceMethodGreedyL *
self, uint8_t * m0, uint8_t * t1, uint8_t * b1, uint8_t * m2,
uint8_t * output, int width)
deinterlace_greedy_scanline_mmxext (GstDeinterlaceMethodGreedyL *
self, const guint8 * m0, const guint8 * t1, const guint8 * b1,
const guint8 * m2, guint8 * output, gint width)
{
mmx_t MaxComb;
@ -327,70 +325,80 @@ deinterlace_greedy_packed422_scanline_mmxext (GstDeinterlaceMethodGreedyL *
emms ();
if (width > 0)
deinterlace_greedy_packed422_scanline_c (self, m0, t1, b1, m2, output,
width);
deinterlace_greedy_scanline_c (self, m0, t1, b1, m2, output, width);
}
#endif
static void
deinterlace_frame_di_greedy (GstDeinterlaceMethod * d_method,
GstDeinterlace * object, GstBuffer * outbuf)
deinterlace_frame_di_greedy_packed (GstDeinterlaceMethod * method,
const GstDeinterlaceField * history, guint history_count,
GstBuffer * outbuf)
{
GstDeinterlaceMethodGreedyL *self =
GST_DEINTERLACE_METHOD_GREEDY_L (d_method);
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (method);
GstDeinterlaceMethodGreedyLClass *klass =
GST_DEINTERLACE_METHOD_GREEDY_L_GET_CLASS (self);
int InfoIsOdd = 0;
int Line;
unsigned int Pitch = object->field_stride;
unsigned char *L1; // ptr to Line1, of 3
unsigned char *L2; // ptr to Line2, the weave line
unsigned char *L3; // ptr to Line3
unsigned char *L2P; // ptr to prev Line2
unsigned char *Dest = GST_BUFFER_DATA (outbuf);
gint InfoIsOdd = 0;
gint Line;
gint RowStride = method->row_stride[0];
gint FieldHeight = method->frame_height / 2;
gint Pitch = method->row_stride[0] * 2;
const guint8 *L1; // ptr to Line1, of 3
const guint8 *L2; // ptr to Line2, the weave line
const guint8 *L3; // ptr to Line3
const guint8 *L2P; // ptr to prev Line2
guint8 *Dest = GST_BUFFER_DATA (outbuf);
// 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.)
if (object->field_history[object->history_count - 1].flags ==
PICTURE_INTERLACED_BOTTOM) {
if (history[history_count - 1].flags == PICTURE_INTERLACED_BOTTOM) {
InfoIsOdd = 1;
L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf);
L1 = GST_BUFFER_DATA (history[history_count - 2].buf);
if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
L1 += RowStride;
L2 = GST_BUFFER_DATA (history[history_count - 1].buf);
if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
L2 += RowStride;
L3 = L1 + Pitch;
L2P =
GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf);
L2P = GST_BUFFER_DATA (history[history_count - 3].buf);
if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
L2P += RowStride;
// copy first even line
oil_memcpy (Dest, L1, object->row_stride);
Dest += object->row_stride;
oil_memcpy (Dest, L1, RowStride);
Dest += RowStride;
} else {
InfoIsOdd = 0;
L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
L2 = GST_BUFFER_DATA (object->field_history[object->history_count -
1].buf) + Pitch;
L1 = GST_BUFFER_DATA (history[history_count - 2].buf);
if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
L1 += RowStride;
L2 = GST_BUFFER_DATA (history[history_count - 1].buf) + Pitch;
if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
L2 += RowStride;
L3 = L1 + Pitch;
L2P =
GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) +
Pitch;
L2P = GST_BUFFER_DATA (history[history_count - 3].buf) + Pitch;
if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
L2P += RowStride;
// copy first even line
oil_memcpy (Dest, GST_BUFFER_DATA (object->field_history[0].buf),
object->row_stride);
Dest += object->row_stride;
oil_memcpy (Dest, GST_BUFFER_DATA (history[0].buf), RowStride);
Dest += RowStride;
// then first odd line
oil_memcpy (Dest, L1, object->row_stride);
Dest += object->row_stride;
oil_memcpy (Dest, L1, RowStride);
Dest += RowStride;
}
for (Line = 0; Line < (object->field_height - 1); ++Line) {
klass->scanline (self, L2, L1, L3, L2P, Dest, object->row_stride);
Dest += object->row_stride;
oil_memcpy (Dest, L3, object->row_stride);
Dest += object->row_stride;
for (Line = 0; Line < (FieldHeight - 1); ++Line) {
klass->scanline (self, L2, L1, L3, L2P, Dest, RowStride);
Dest += RowStride;
oil_memcpy (Dest, L3, RowStride);
Dest += RowStride;
L1 += Pitch;
L2 += Pitch;
@ -399,18 +407,17 @@ deinterlace_frame_di_greedy (GstDeinterlaceMethod * d_method,
}
if (InfoIsOdd) {
oil_memcpy (Dest, L2, object->row_stride);
oil_memcpy (Dest, L2, RowStride);
}
}
G_DEFINE_TYPE (GstDeinterlaceMethodGreedyL, gst_deinterlace_method_greedy_l,
GST_TYPE_DEINTERLACE_METHOD);
enum
{
ARG_0,
ARG_MAX_COMB
PROP_0,
PROP_MAX_COMB
};
static void
@ -420,7 +427,7 @@ gst_deinterlace_method_greedy_l_set_property (GObject * object, guint prop_id,
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object);
switch (prop_id) {
case ARG_MAX_COMB:
case PROP_MAX_COMB:
self->max_comb = g_value_get_uint (value);
break;
default:
@ -435,7 +442,7 @@ gst_deinterlace_method_greedy_l_get_property (GObject * object, guint prop_id,
GstDeinterlaceMethodGreedyL *self = GST_DEINTERLACE_METHOD_GREEDY_L (object);
switch (prop_id) {
case ARG_MAX_COMB:
case PROP_MAX_COMB:
g_value_set_uint (value, self->max_comb);
break;
default:
@ -456,28 +463,30 @@ gst_deinterlace_method_greedy_l_class_init (GstDeinterlaceMethodGreedyLClass *
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_object_class_install_property (gobject_class, PROP_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;
dim_class->deinterlace_frame_yuy2 = deinterlace_frame_di_greedy_packed;
dim_class->deinterlace_frame_yvyu = deinterlace_frame_di_greedy_packed;
#ifdef BUILD_X86_ASM
if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
klass->scanline = deinterlace_greedy_packed422_scanline_mmxext;
klass->scanline = deinterlace_greedy_scanline_mmxext;
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
klass->scanline = deinterlace_greedy_packed422_scanline_mmx;
klass->scanline = deinterlace_greedy_scanline_mmx;
} else {
klass->scanline = deinterlace_greedy_packed422_scanline_c;
klass->scanline = deinterlace_greedy_scanline_c;
}
#else
klass->scanline = deinterlace_greedy_packed422_scanline_c;
klass->scanline = deinterlace_greedy_scanline_c;
#endif
}

View file

@ -2,7 +2,7 @@
*
* GStreamer
* Copyright (c) 2001 Tom Barry. All rights reserved.
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
* Copyright (C) 2008,2010 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
@ -15,7 +15,7 @@
* 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
* License aglong with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
@ -30,29 +30,28 @@
#include "x86-64_macros.inc"
static void
FUNCT_NAME (GstDeinterlaceMethodGreedyH *self, uint8_t * L1, uint8_t * L2, uint8_t * L3, uint8_t * L2P,
uint8_t * Dest, int size)
FUNCT_NAME (GstDeinterlaceMethodGreedyH *self, const guint8 * L1, const guint8 * L2, const guint8 * L3, const guint8 * L2P, guint8 * Dest, gint width)
{
// in tight loop some vars are accessed faster in local storage
int64_t YMask = 0x00ff00ff00ff00ffull; // to keep only luma
int64_t UVMask = 0xff00ff00ff00ff00ull; // to keep only chroma
int64_t ShiftMask = 0xfefefefefefefefeull; // to avoid shifting chroma to luma
int64_t QW256 = 0x0100010001000100ull; // 4 256's
int64_t MaxComb;
int64_t MotionThreshold;
int64_t MotionSense;
int64_t i;
long LoopCtr;
long oldbx;
gint64 YMask = 0x00ff00ff00ff00ffull; // to keep only luma
gint64 UVMask = 0xff00ff00ff00ff00ull; // to keep only chroma
gint64 ShiftMask = 0xfefefefefefefefeull; // to avoid shifting chroma to luma
gint64 QW256 = 0x0100010001000100ull; // 4 256's
gint64 MaxComb;
gint64 MotionThreshold;
gint64 MotionSense;
gint64 i;
glong LoopCtr;
glong oldbx;
gint64 QW256B;
gint64 LastAvg = 0; //interp value from left qword
int64_t QW256B;
int64_t LastAvg = 0; //interp value from left qword
// FIXME: Use C implementation if the width is not a multiple of 4
// Do something more optimal later
if (size % 8 != 0)
greedyDScaler_C (self, L1, L2, L3, L2P, Dest, size);
if (width % 4 != 0)
C_FUNCT (self, L1, L2, L3, L2P, Dest, width);
// Set up our two parms that are actually evaluated for each pixel
i = self->max_comb;
@ -68,7 +67,7 @@ FUNCT_NAME (GstDeinterlaceMethodGreedyH *self, uint8_t * L1, uint8_t * L2, uint8
i = 0xffffffff - 256;
QW256B = i << 48 | i << 32 | i << 16 | i; // save a couple instr on PMINSW instruct.
LoopCtr = size / 8 - 1; // there are LineLength / 8 qwords per line but do 1 less, adj at end of loop
LoopCtr = width / 4 - 1; // there are LineLength / 4 qwords per line but do 1 less, adj at end of loop
// For ease of reading, the comments below assume that we're operating on an odd
// field (i.e., that InfoIsOdd is true). Assume the obvious for even lines..

View file

@ -2,7 +2,7 @@
*
* GStreamer
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
* Copyright (C) 2008,2010 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
@ -32,10 +32,9 @@
#include "greedyhmacros.h"
#include <stdlib.h>
#include "_stdint.h"
#include <string.h>
#include "gst/gst.h"
#include <gst/gst.h>
#include "plugins.h"
#include "gstdeinterlace.h"
@ -54,41 +53,45 @@ typedef struct
guint max_comb, motion_threshold, motion_sense;
} GstDeinterlaceMethodGreedyH;
typedef void (*ScanlineFunction) (GstDeinterlaceMethodGreedyH * self,
const guint8 * L2, const guint8 * L1, const guint8 * L3, const guint8 * L2P,
guint8 * Dest, gint width);
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);
ScanlineFunction scanline_yuy2; /* This is for YVYU too */
} GstDeinterlaceMethodGreedyHClass;
static void
greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2,
uint8_t * L3, uint8_t * L2P, uint8_t * Dest, int size)
greedyh_scanline_yuy2_C (GstDeinterlaceMethodGreedyH * self, const guint8 * L1,
const guint8 * L2, const guint8 * L3, const guint8 * L2P, guint8 * Dest,
gint width)
{
int Pos;
uint8_t l1_l, l1_1_l, l3_l, l3_1_l;
uint8_t l1_c, l1_1_c, l3_c, l3_1_c;
uint8_t avg_l, avg_c, avg_l_1, avg_c_1;
uint8_t avg_l__1 = 0, avg_c__1 = 0;
uint8_t avg_s_l, avg_s_c;
uint8_t avg_sc_l, avg_sc_c;
uint8_t best_l, best_c;
uint16_t mov_l;
uint8_t out_l, out_c;
uint8_t l2_l, l2_c, lp2_l, lp2_c;
uint8_t l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff;
uint8_t min_l, min_c, max_l, max_c;
gint Pos;
guint8 l1_l, l1_1_l, l3_l, l3_1_l;
guint8 l1_c, l1_1_c, l3_c, l3_1_c;
guint8 avg_l, avg_c, avg_l_1, avg_c_1;
guint8 avg_l__1 = 0, avg_c__1 = 0;
guint8 avg_s_l, avg_s_c;
guint8 avg_sc_l, avg_sc_c;
guint8 best_l, best_c;
guint16 mov_l;
guint8 out_l, out_c;
guint8 l2_l, l2_c, lp2_l, lp2_c;
guint8 l2_l_diff, l2_c_diff, lp2_l_diff, lp2_c_diff;
guint8 min_l, min_c, max_l, max_c;
guint max_comb = self->max_comb;
guint motion_sense = self->motion_sense;
guint motion_threshold = self->motion_threshold;
for (Pos = 0; Pos < size; Pos += 2) {
for (Pos = 0; Pos < width; Pos++) {
l1_l = L1[0];
l1_c = L1[1];
l3_l = L3[0];
l3_c = L3[1];
if (Pos == size - 1) {
if (Pos == width - 1) {
l1_1_l = l1_l;
l1_1_c = l1_c;
l3_1_l = l3_l;
@ -207,7 +210,8 @@ greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2,
#define IS_MMXEXT
#define SIMD_TYPE MMXEXT
#define FUNCT_NAME greedyDScaler_MMXEXT
#define C_FUNCT greedyh_scanline_yuy2_C
#define FUNCT_NAME greedyh_scanline_yuy2_MMXEXT
#include "greedyh.asm"
#undef SIMD_TYPE
#undef IS_MMXEXT
@ -215,7 +219,7 @@ greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2,
#define IS_3DNOW
#define SIMD_TYPE 3DNOW
#define FUNCT_NAME greedyDScaler_3DNOW
#define FUNCT_NAME greedyh_scanline_yuy2_3DNOW
#include "greedyh.asm"
#undef SIMD_TYPE
#undef IS_3DNOW
@ -223,74 +227,95 @@ greedyDScaler_C (GstDeinterlaceMethodGreedyH * self, uint8_t * L1, uint8_t * L2,
#define IS_MMX
#define SIMD_TYPE MMX
#define FUNCT_NAME greedyDScaler_MMX
#define FUNCT_NAME greedyh_scanline_yuy2_MMX
#include "greedyh.asm"
#undef SIMD_TYPE
#undef IS_MMX
#undef FUNCT_NAME
#undef C_FUNCT
#endif
static void
deinterlace_frame_di_greedyh (GstDeinterlaceMethod * d_method,
GstDeinterlace * object, GstBuffer * outbuf)
deinterlace_frame_di_greedyh_packed (GstDeinterlaceMethod * method,
const GstDeinterlaceField * history, guint history_count,
GstBuffer * outbuf)
{
GstDeinterlaceMethodGreedyH *self =
GST_DEINTERLACE_METHOD_GREEDY_H (d_method);
GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (method);
GstDeinterlaceMethodGreedyHClass *klass =
GST_DEINTERLACE_METHOD_GREEDY_H_GET_CLASS (self);
int InfoIsOdd = 0;
int Line;
unsigned int Pitch = object->field_stride;
gint InfoIsOdd = 0;
gint Line;
gint RowStride = method->row_stride[0];
gint FieldHeight = method->frame_height / 2;
gint Pitch = method->row_stride[0] * 2;
const guint8 *L1; // ptr to Line1, of 3
const guint8 *L2; // ptr to Line2, the weave line
const guint8 *L3; // ptr to Line3
const guint8 *L2P; // ptr to prev Line2
guint8 *Dest = GST_BUFFER_DATA (outbuf);
ScanlineFunction scanline;
unsigned char *L1; // ptr to Line1, of 3
unsigned char *L2; // ptr to Line2, the weave line
unsigned char *L3; // ptr to Line3
unsigned char *L2P; // ptr to prev Line2
unsigned char *Dest = GST_BUFFER_DATA (outbuf);
switch (method->format) {
case GST_VIDEO_FORMAT_YUY2:
case GST_VIDEO_FORMAT_YVYU:
scanline = klass->scanline_yuy2;
break;
default:
g_assert_not_reached ();
break;
}
// 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.)
if (object->field_history[object->history_count - 1].flags ==
PICTURE_INTERLACED_BOTTOM) {
if (history[history_count - 1].flags == PICTURE_INTERLACED_BOTTOM) {
InfoIsOdd = 1;
L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
L2 = GST_BUFFER_DATA (object->field_history[object->history_count - 1].buf);
L1 = GST_BUFFER_DATA (history[history_count - 2].buf);
if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
L1 += RowStride;
L2 = GST_BUFFER_DATA (history[history_count - 1].buf);
if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
L2 += RowStride;
L3 = L1 + Pitch;
L2P =
GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf);
L2P = GST_BUFFER_DATA (history[history_count - 3].buf);
if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
L2P += RowStride;
// copy first even line
oil_memcpy (Dest, L1, object->row_stride);
Dest += object->row_stride;
oil_memcpy (Dest, L1, RowStride);
Dest += RowStride;
} else {
InfoIsOdd = 0;
L1 = GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf);
L2 = GST_BUFFER_DATA (object->field_history[object->history_count -
1].buf) + Pitch;
L1 = GST_BUFFER_DATA (history[history_count - 2].buf);
if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
L1 += RowStride;
L2 = GST_BUFFER_DATA (history[history_count - 1].buf) + Pitch;
if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
L2 += RowStride;
L3 = L1 + Pitch;
L2P =
GST_BUFFER_DATA (object->field_history[object->history_count - 3].buf) +
Pitch;
L2P = GST_BUFFER_DATA (history[history_count - 3].buf) + Pitch;
if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
L2P += RowStride;
// copy first even line
oil_memcpy (Dest,
GST_BUFFER_DATA (object->field_history[object->history_count - 2].buf),
object->row_stride);
Dest += object->row_stride;
oil_memcpy (Dest, L1, RowStride);
Dest += RowStride;
// then first odd line
oil_memcpy (Dest, L1, object->row_stride);
Dest += object->row_stride;
oil_memcpy (Dest, L1, RowStride);
Dest += RowStride;
}
for (Line = 0; Line < (object->field_height - 1); ++Line) {
klass->scanline (self, L1, L2, L3, L2P, Dest, object->row_stride);
Dest += object->row_stride;
oil_memcpy (Dest, L3, object->row_stride);
Dest += object->row_stride;
for (Line = 0; Line < (FieldHeight - 1); ++Line) {
scanline (self, L1, L2, L3, L2P, Dest, RowStride);
Dest += RowStride;
oil_memcpy (Dest, L3, RowStride);
Dest += RowStride;
L1 += Pitch;
L2 += Pitch;
@ -299,7 +324,7 @@ deinterlace_frame_di_greedyh (GstDeinterlaceMethod * d_method,
}
if (InfoIsOdd) {
oil_memcpy (Dest, L2, object->row_stride);
oil_memcpy (Dest, L2, RowStride);
}
}
@ -308,10 +333,10 @@ G_DEFINE_TYPE (GstDeinterlaceMethodGreedyH, gst_deinterlace_method_greedy_h,
enum
{
ARG_0,
ARG_MAX_COMB,
ARG_MOTION_THRESHOLD,
ARG_MOTION_SENSE
PROP_0,
PROP_MAX_COMB,
PROP_MOTION_THRESHOLD,
PROP_MOTION_SENSE
};
static void
@ -321,13 +346,13 @@ gst_deinterlace_method_greedy_h_set_property (GObject * object, guint prop_id,
GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
switch (prop_id) {
case ARG_MAX_COMB:
case PROP_MAX_COMB:
self->max_comb = g_value_get_uint (value);
break;
case ARG_MOTION_THRESHOLD:
case PROP_MOTION_THRESHOLD:
self->motion_threshold = g_value_get_uint (value);
break;
case ARG_MOTION_SENSE:
case PROP_MOTION_SENSE:
self->motion_sense = g_value_get_uint (value);
break;
default:
@ -342,13 +367,13 @@ gst_deinterlace_method_greedy_h_get_property (GObject * object, guint prop_id,
GstDeinterlaceMethodGreedyH *self = GST_DEINTERLACE_METHOD_GREEDY_H (object);
switch (prop_id) {
case ARG_MAX_COMB:
case PROP_MAX_COMB:
g_value_set_uint (value, self->max_comb);
break;
case ARG_MOTION_THRESHOLD:
case PROP_MOTION_THRESHOLD:
g_value_set_uint (value, self->motion_threshold);
break;
case ARG_MOTION_SENSE:
case PROP_MOTION_SENSE:
g_value_set_uint (value, self->motion_sense);
break;
default:
@ -369,20 +394,20 @@ gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass *
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_object_class_install_property (gobject_class, PROP_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_object_class_install_property (gobject_class, PROP_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_object_class_install_property (gobject_class, PROP_MOTION_SENSE,
g_param_spec_uint ("motion-sense",
"Motion Sense",
"Motion Sense",
@ -390,23 +415,25 @@ gst_deinterlace_method_greedy_h_class_init (GstDeinterlaceMethodGreedyHClass *
);
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;
dim_class->deinterlace_frame_yuy2 = deinterlace_frame_di_greedyh_packed;
dim_class->deinterlace_frame_yvyu = deinterlace_frame_di_greedyh_packed;
#ifdef BUILD_X86_ASM
if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
klass->scanline = greedyDScaler_MMXEXT;
klass->scanline_yuy2 = greedyh_scanline_yuy2_MMXEXT;
} else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) {
klass->scanline = greedyDScaler_3DNOW;
klass->scanline_yuy2 = greedyh_scanline_yuy2_3DNOW;
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
klass->scanline = greedyDScaler_MMX;
klass->scanline_yuy2 = greedyh_scanline_yuy2_MMX;
} else {
klass->scanline = greedyDScaler_C;
klass->scanline_yuy2 = greedyh_scanline_yuy2_C;
}
#else
klass->scanline = greedyDScaler_C;
klass->scanline_yuy2 = greedyh_scanline_yuy2_C;
#endif
}

View file

@ -1,6 +1,6 @@
/**
* Copyright (C) 2002 Billy Biggs <vektor@dumbterm.net>.
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
* Copyright (C) 2008,2010 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 Lesser General Public
@ -27,7 +27,6 @@
# include "config.h"
#endif
#include "_stdint.h"
#include "gstdeinterlace.h"
#include <string.h>
@ -42,33 +41,36 @@
GType gst_deinterlace_method_linear_get_type (void);
typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodLinear;
typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodLinearClass;
static void
deinterlace_scanline_linear_c (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_linear_c (GstDeinterlaceSimpleMethod * self,
guint8 * out, const guint8 * s1, const guint8 * s2, gint size)
{
gint i;
width *= 2;
for (i = 0; i < width; i++)
out[i] = (scanlines->t0[i] + scanlines->b0[i]) / 2;
for (i = 0; i < size; i++)
out[i] = (s1[i] + s2[i]) / 2;
}
static void
deinterlace_scanline_linear_packed_c (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
deinterlace_scanline_linear_c (self, out, scanlines->t0, scanlines->b0,
self->parent.row_stride[0]);
}
#ifdef BUILD_X86_ASM
#include "mmx.h"
static void
deinterlace_scanline_linear_mmx (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_linear_mmx (GstDeinterlaceSimpleMethod * self,
guint8 * out, const guint8 * bot, const guint8 * top, gint size)
{
const mmx_t shiftmask = { 0xfefffefffefffeffULL }; /* To avoid shifting chroma to luma. */
int i;
guint8 *bot = scanlines->b0, *top = scanlines->t0;
for (i = width / 16; i; --i) {
for (i = size / 32; i; --i) {
movq_m2r (*bot, mm0);
movq_m2r (*top, mm1);
movq_m2r (*(bot + 8), mm2);
@ -105,9 +107,9 @@ deinterlace_scanline_linear_mmx (GstDeinterlaceMethod * self,
top += 32;
bot += 32;
}
width = (width & 0xf);
size = (size & 0x1f);
for (i = width / 4; i; --i) {
for (i = size / 8; i; --i) {
movq_m2r (*bot, mm0);
movq_m2r (*top, mm1);
pand_m2r (shiftmask, mm0);
@ -120,26 +122,32 @@ deinterlace_scanline_linear_mmx (GstDeinterlaceMethod * self,
top += 8;
bot += 8;
}
width = width & 0x7;
emms ();
size = size & 0xf;
/* Handle last few pixels. */
for (i = width * 2; i; --i) {
for (i = size; i; --i) {
*out++ = ((*top++) + (*bot++)) >> 1;
}
}
emms ();
static void
deinterlace_scanline_linear_packed_mmx (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
deinterlace_scanline_linear_mmx (self, out, scanlines->t0, scanlines->b0,
self->parent.row_stride[0]);
}
#include "sse.h"
static void
deinterlace_scanline_linear_mmxext (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_linear_mmxext (GstDeinterlaceSimpleMethod * self,
guint8 * out, const guint8 * bot, const guint8 * top, gint size)
{
gint i;
guint8 *bot = scanlines->b0, *top = scanlines->t0;
for (i = width / 16; i; --i) {
for (i = size / 32; i; --i) {
movq_m2r (*bot, mm0);
movq_m2r (*top, mm1);
movq_m2r (*(bot + 8), mm2);
@ -160,9 +168,9 @@ deinterlace_scanline_linear_mmxext (GstDeinterlaceMethod * self,
top += 32;
bot += 32;
}
width = (width & 0xf);
size = (size & 0x1f);
for (i = width / 4; i; --i) {
for (i = size / 8; i; --i) {
movq_m2r (*bot, mm0);
movq_m2r (*top, mm1);
pavgb_r2r (mm1, mm0);
@ -171,14 +179,22 @@ deinterlace_scanline_linear_mmxext (GstDeinterlaceMethod * self,
top += 8;
bot += 8;
}
width = width & 0x7;
emms ();
size = size & 0xf;
/* Handle last few pixels. */
for (i = width * 2; i; --i) {
for (i = size; i; --i) {
*out++ = ((*top++) + (*bot++)) >> 1;
}
}
emms ();
static void
deinterlace_scanline_linear_packed_mmxext (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
deinterlace_scanline_linear_mmxext (self, out, scanlines->t0, scanlines->b0,
self->parent.row_stride[0]);
}
#endif
@ -202,13 +218,20 @@ gst_deinterlace_method_linear_class_init (GstDeinterlaceMethodLinearClass *
dim_class->nick = "linear";
dim_class->latency = 0;
dism_class->interpolate_scanline = deinterlace_scanline_linear_c;
dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_linear_packed_c;
dism_class->interpolate_scanline_yvyu = deinterlace_scanline_linear_packed_c;
#ifdef BUILD_X86_ASM
if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
dism_class->interpolate_scanline = deinterlace_scanline_linear_mmxext;
} else if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
dism_class->interpolate_scanline = deinterlace_scanline_linear_mmx;
dism_class->interpolate_scanline_yuy2 =
deinterlace_scanline_linear_packed_mmxext;
dism_class->interpolate_scanline_yvyu =
deinterlace_scanline_linear_packed_mmxext;
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
dism_class->interpolate_scanline_yuy2 =
deinterlace_scanline_linear_packed_mmx;
dism_class->interpolate_scanline_yvyu =
deinterlace_scanline_linear_packed_mmx;
}
#endif
}

View file

@ -4,7 +4,7 @@
* sources.
*
* Copyright (C) 2002 Billy Biggs <vektor@dumbterm.net>.
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
* Copyright (C) 2008,2010 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 Lesser General Public
@ -31,7 +31,6 @@
# include "config.h"
#endif
#include "_stdint.h"
#include "gstdeinterlace.h"
#include <string.h>
@ -46,57 +45,55 @@
GType gst_deinterlace_method_linear_blend_get_type (void);
typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodLinearBlend;
typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodLinearBlendClass;
static inline void
deinterlace_scanline_linear_blend_c (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_linear_blend_c (GstDeinterlaceSimpleMethod * self,
guint8 * out, const guint8 * t0, const guint8 * b0, const guint8 * m1,
gint size)
{
guint8 *t0 = scanlines->t0;
guint8 *b0 = scanlines->b0;
guint8 *m1 = scanlines->m1;
width *= 2;
while (width--) {
while (size--) {
*out++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2;
}
}
static inline void
deinterlace_scanline_linear_blend2_c (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
static void
deinterlace_scanline_linear_blend_packed_c (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
guint8 *m0 = scanlines->m0;
guint8 *t1 = scanlines->t1;
guint8 *b1 = scanlines->b1;
deinterlace_scanline_linear_blend_c (self, out, scanlines->t0, scanlines->b0,
scanlines->m1, self->parent.row_stride[0]);
}
width *= 2;
while (width--) {
static inline void
deinterlace_scanline_linear_blend2_c (GstDeinterlaceSimpleMethod * self,
guint8 * out, const guint8 * m0, const guint8 * t1, const guint8 * b1,
gint size)
{
while (size--) {
*out++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2;
}
}
static void
deinterlace_scanline_linear_blend2_packed_c (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
deinterlace_scanline_linear_blend2_c (self, out, scanlines->m0, scanlines->t1,
scanlines->b1, self->parent.row_stride[0]);
}
#ifdef BUILD_X86_ASM
#include "mmx.h"
static inline void
deinterlace_scanline_linear_blend_mmx (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_linear_blend_mmx (GstDeinterlaceSimpleMethod * self,
guint8 * out, const guint8 * t0, const guint8 * b0, const guint8 * m1,
gint size)
{
guint8 *t0 = scanlines->t0;
guint8 *b0 = scanlines->b0;
guint8 *m1 = scanlines->m1;
gint i;
// Get width in bytes.
width *= 2;
i = width / 8;
width -= i * 8;
i = size / 8;
size -= i * 8;
pxor_r2r (mm7, mm7);
while (i--) {
@ -134,26 +131,29 @@ deinterlace_scanline_linear_blend_mmx (GstDeinterlaceMethod * self,
b0 += 8;
m1 += 8;
}
while (width--) {
emms ();
while (size--) {
*out++ = (*t0++ + *b0++ + (*m1++ << 1)) >> 2;
}
emms ();
}
static void
deinterlace_scanline_linear_blend_packed_mmx (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
deinterlace_scanline_linear_blend_mmx (self, out, scanlines->t0,
scanlines->b0, scanlines->m1, self->parent.row_stride[0]);
}
static inline void
deinterlace_scanline_linear_blend2_mmx (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_linear_blend2_mmx (GstDeinterlaceSimpleMethod * self,
guint8 * out, const guint8 * m0, const guint8 * t1, const guint8 * b1,
gint size)
{
guint8 *m0 = scanlines->m0;
guint8 *t1 = scanlines->t1;
guint8 *b1 = scanlines->b1;
gint i;
// Get width in bytes.
width *= 2;
i = width / 8;
width -= i * 8;
i = size / 8;
size -= i * 8;
pxor_r2r (mm7, mm7);
while (i--) {
@ -191,10 +191,19 @@ deinterlace_scanline_linear_blend2_mmx (GstDeinterlaceMethod * self,
b1 += 8;
m0 += 8;
}
while (width--) {
emms ();
while (size--) {
*out++ = (*t1++ + *b1++ + (*m0++ << 1)) >> 2;
}
emms ();
}
static void
deinterlace_scanline_linear_blend2_packed_mmx (GstDeinterlaceSimpleMethod *
self, guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
deinterlace_scanline_linear_blend2_mmx (self, out, scanlines->m0,
scanlines->t1, scanlines->b1, self->parent.row_stride[0]);
}
#endif
@ -218,13 +227,23 @@ static void
dim_class->nick = "linearblend";
dim_class->latency = 0;
dism_class->interpolate_scanline = deinterlace_scanline_linear_blend_c;
dism_class->copy_scanline = deinterlace_scanline_linear_blend2_c;
dism_class->interpolate_scanline_yuy2 =
deinterlace_scanline_linear_blend_packed_c;
dism_class->interpolate_scanline_yvyu =
deinterlace_scanline_linear_blend_packed_c;
dism_class->copy_scanline_yuy2 = deinterlace_scanline_linear_blend2_packed_c;
dism_class->copy_scanline_yvyu = deinterlace_scanline_linear_blend2_packed_c;
#ifdef BUILD_X86_ASM
if (cpu_flags & OIL_IMPL_FLAG_MMX) {
dism_class->interpolate_scanline = deinterlace_scanline_linear_blend_mmx;
dism_class->copy_scanline = deinterlace_scanline_linear_blend2_mmx;
dism_class->interpolate_scanline_yuy2 =
deinterlace_scanline_linear_blend_packed_mmx;
dism_class->interpolate_scanline_yvyu =
deinterlace_scanline_linear_blend_packed_mmx;
dism_class->copy_scanline_yuy2 =
deinterlace_scanline_linear_blend2_packed_mmx;
dism_class->copy_scanline_yvyu =
deinterlace_scanline_linear_blend2_packed_mmx;
}
#endif
}

View file

@ -1,6 +1,6 @@
/**
* Double lines
* Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* Copyright (C) 2008,2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -22,7 +22,6 @@
# include "config.h"
#endif
#include "_stdint.h"
#include "gstdeinterlace.h"
#include <string.h>
@ -37,16 +36,13 @@
GType gst_deinterlace_method_scaler_bob_get_type (void);
typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodScalerBob;
typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodScalerBobClass;
static void
deinterlace_scanline_scaler_bob (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_scaler_bob_packed (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
oil_memcpy (out, scanlines->t0, parent->row_stride);
oil_memcpy (out, scanlines->t0, self->parent.row_stride[0]);
}
G_DEFINE_TYPE (GstDeinterlaceMethodScalerBob, gst_deinterlace_method_scaler_bob,
@ -65,7 +61,10 @@ gst_deinterlace_method_scaler_bob_class_init (GstDeinterlaceMethodScalerBobClass
dim_class->nick = "scalerbob";
dim_class->latency = 0;
dism_class->interpolate_scanline = deinterlace_scanline_scaler_bob;
dism_class->interpolate_scanline_yuy2 =
deinterlace_scanline_scaler_bob_packed;
dism_class->interpolate_scanline_yvyu =
deinterlace_scanline_scaler_bob_packed;
}
static void

View file

@ -1,6 +1,6 @@
/**
* Copyright (C) 2004 Billy Biggs <vektor@dumbterm.net>
* Copyright (C) 2008 Sebastian Dröge <slomo@collabora.co.uk>
* Copyright (C) 2008,2010 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,10 +28,9 @@
#endif
#include <stdlib.h>
#include "_stdint.h"
#include <string.h>
#include "gst/gst.h"
#include <gst/gst.h>
#include "gstdeinterlace.h"
#include "plugins.h"
@ -51,26 +50,19 @@ typedef struct
gboolean strange_bob;
} GstDeinterlaceMethodTomsMoComp;
typedef struct
{
GstDeinterlaceMethodClass parent_class;
} GstDeinterlaceMethodTomsMoCompClass;
typedef GstDeinterlaceMethodClass GstDeinterlaceMethodTomsMoCompClass;
static int
Fieldcopy (void *dest, const void *src, size_t count,
int rows, int dst_pitch, int src_pitch)
static void
Fieldcopy (guint8 * dest, const guint8 * src, gint count,
gint rows, gint dst_pitch, gint src_pitch)
{
unsigned char *pDest = (unsigned char *) dest;
unsigned char *pSrc = (unsigned char *) src;
int i;
gint i;
for (i = 0; i < rows; i++) {
oil_memcpy (pDest, pSrc, count);
pSrc += src_pitch;
pDest += dst_pitch;
oil_memcpy (dest, src, count);
src += src_pitch;
dest += dst_pitch;
}
return 0;
}
#define USE_FOR_DSCALER
@ -119,9 +111,9 @@ G_DEFINE_TYPE (GstDeinterlaceMethodTomsMoComp,
enum
{
ARG_0,
ARG_SEARCH_EFFORT,
ARG_STRANGE_BOB
PROP_0,
PROP_SEARCH_EFFORT,
PROP_STRANGE_BOB
};
static void
@ -132,10 +124,10 @@ gst_deinterlace_method_tomsmocomp_set_property (GObject * object, guint prop_id,
GST_DEINTERLACE_METHOD_TOMSMOCOMP (object);
switch (prop_id) {
case ARG_SEARCH_EFFORT:
case PROP_SEARCH_EFFORT:
self->search_effort = g_value_get_uint (value);
break;
case ARG_STRANGE_BOB:
case PROP_STRANGE_BOB:
self->strange_bob = g_value_get_boolean (value);
break;
default:
@ -151,10 +143,10 @@ gst_deinterlace_method_tomsmocomp_get_property (GObject * object, guint prop_id,
GST_DEINTERLACE_METHOD_TOMSMOCOMP (object);
switch (prop_id) {
case ARG_SEARCH_EFFORT:
case PROP_SEARCH_EFFORT:
g_value_set_uint (value, self->search_effort);
break;
case ARG_STRANGE_BOB:
case PROP_STRANGE_BOB:
g_value_set_boolean (value, self->strange_bob);
break;
default:
@ -175,13 +167,13 @@ static void
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_object_class_install_property (gobject_class, PROP_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_object_class_install_property (gobject_class, PROP_STRANGE_BOB,
g_param_spec_boolean ("strange-bob",
"Strange Bob",
"Use strange bob", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)
@ -194,16 +186,21 @@ static void
#ifdef BUILD_X86_ASM
if (cpu_flags & OIL_IMPL_FLAG_MMXEXT) {
dim_class->deinterlace_frame = tomsmocompDScaler_MMXEXT;
dim_class->deinterlace_frame_yuy2 = tomsmocompDScaler_MMXEXT;
dim_class->deinterlace_frame_yvyu = tomsmocompDScaler_MMXEXT;
} else if (cpu_flags & OIL_IMPL_FLAG_3DNOW) {
dim_class->deinterlace_frame = tomsmocompDScaler_3DNOW;
dim_class->deinterlace_frame_yuy2 = tomsmocompDScaler_3DNOW;
dim_class->deinterlace_frame_yvyu = tomsmocompDScaler_3DNOW;
} else if (cpu_flags & OIL_IMPL_FLAG_MMX) {
dim_class->deinterlace_frame = tomsmocompDScaler_MMX;
dim_class->deinterlace_frame_yuy2 = tomsmocompDScaler_MMX;
dim_class->deinterlace_frame_yvyu = tomsmocompDScaler_MMX;
} else {
dim_class->deinterlace_frame = tomsmocompDScaler_C;
dim_class->deinterlace_frame_yuy2 = tomsmocompDScaler_C;
dim_class->deinterlace_frame_yvyu = tomsmocompDScaler_C;
}
#else
dim_class->deinterlace_frame = tomsmocompDScaler_C;
dim_class->deinterlace_frame_yuy2 = tomsmocompDScaler_C;
dim_class->deinterlace_frame_yvyu = tomsmocompDScaler_C;
#endif
}

View file

@ -61,36 +61,44 @@
#define SEFUNC(x) Search_Effort_C_##x(src_pitch, dst_pitch, rowsize, pWeaveSrc, pWeaveSrcP, pWeaveDest, IsOdd, pCopySrc, pCopySrcP, FldHeight)
#endif
static void FUNCT_NAME(GstDeinterlaceMethod *d_method, GstDeinterlace* object, GstBuffer *outbuf)
static void FUNCT_NAME(GstDeinterlaceMethod *d_method, const GstDeinterlaceField* history, guint history_count, GstBuffer *outbuf)
{
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;
glong SearchEffort = self->search_effort;
gint UseStrangeBob = self->strange_bob;
gint IsOdd;
const guint8 *pWeaveSrc;
const guint8 *pWeaveSrcP;
guint8 *pWeaveDest;
const guint8 *pCopySrc;
const guint8 *pCopySrcP;
guint8 *pCopyDest;
gint src_pitch;
gint dst_pitch;
gint rowsize;
gint FldHeight;
/* double stride do address just every odd/even scanline */
src_pitch = object->field_stride;
dst_pitch = object->row_stride;
rowsize = object->row_stride;
FldHeight = object->field_height;
src_pitch = self->parent.row_stride[0]*2;
dst_pitch = self->parent.row_stride[0];
rowsize = self->parent.row_stride[0];
FldHeight = self->parent.frame_height / 2;
pCopySrc = GST_BUFFER_DATA(object->field_history[object->history_count-1].buf);
pCopySrcP = GST_BUFFER_DATA(object->field_history[object->history_count-3].buf);
pWeaveSrc = GST_BUFFER_DATA(object->field_history[object->history_count-2].buf);
pWeaveSrcP = GST_BUFFER_DATA(object->field_history[object->history_count-4].buf);
pCopySrc = GST_BUFFER_DATA(history[history_count-1].buf);
if (history[history_count - 1].flags & PICTURE_INTERLACED_BOTTOM)
pCopySrc += rowsize;
pCopySrcP = GST_BUFFER_DATA(history[history_count-3].buf);
if (history[history_count - 3].flags & PICTURE_INTERLACED_BOTTOM)
pCopySrcP += rowsize;
pWeaveSrc = GST_BUFFER_DATA(history[history_count-2].buf);
if (history[history_count - 2].flags & PICTURE_INTERLACED_BOTTOM)
pWeaveSrc += rowsize;
pWeaveSrcP = GST_BUFFER_DATA(history[history_count-4].buf);
if (history[history_count - 4].flags & PICTURE_INTERLACED_BOTTOM)
pWeaveSrcP += rowsize;
/* use bottom field and interlace top field */
if (object->field_history[object->history_count-2].flags == PICTURE_INTERLACED_BOTTOM) {
if (history[history_count-2].flags == PICTURE_INTERLACED_BOTTOM) {
IsOdd = 1;
// if we have an odd field we copy an even field and weave an odd field

View file

@ -3,7 +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>
* Copyright (C) 2008,2010 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
@ -33,7 +33,6 @@
# include "config.h"
#endif
#include "_stdint.h"
#include "gstdeinterlace.h"
#include <string.h>
@ -62,16 +61,10 @@ typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodVFIRClass;
* C implementation.
*/
static inline void
deinterlace_line_c (GstDeinterlaceMethod * self, GstDeinterlace * parent,
guint8 * dst, GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_c (guint8 * dst, const guint8 * lum_m4, const guint8 * lum_m3,
const guint8 * lum_m2, const guint8 * lum_m1, const guint8 * lum, gint size)
{
gint sum;
guint8 *lum_m4 = scanlines->tt1;
guint8 *lum_m3 = scanlines->t0;
guint8 *lum_m2 = scanlines->m1;
guint8 *lum_m1 = scanlines->b0;
guint8 *lum = scanlines->bb1;
gint size = width * 2;
for (; size >= 0; size--) {
sum = -lum_m4[0];
@ -89,18 +82,27 @@ deinterlace_line_c (GstDeinterlaceMethod * self, GstDeinterlace * parent,
}
}
static void
deinterlace_line_packed_c (GstDeinterlaceSimpleMethod * self, guint8 * dst,
const GstDeinterlaceScanlineData * scanlines)
{
const guint8 *lum_m4 = scanlines->tt1;
const guint8 *lum_m3 = scanlines->t0;
const guint8 *lum_m2 = scanlines->m1;
const guint8 *lum_m1 = scanlines->b0;
const guint8 *lum = scanlines->bb1;
gint size = self->parent.row_stride[0];
deinterlace_c (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size);
}
#ifdef BUILD_X86_ASM
#include "mmx.h"
static void
deinterlace_line_mmx (GstDeinterlaceMethod * self, GstDeinterlace * parent,
guint8 * dst, GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_mmx (guint8 * dst, const guint8 * lum_m4, const guint8 * lum_m3,
const guint8 * lum_m2, const guint8 * lum_m1, const guint8 * lum, gint size)
{
mmx_t rounder;
guint8 *lum_m4 = scanlines->tt1;
guint8 *lum_m3 = scanlines->t0;
guint8 *lum_m2 = scanlines->m1;
guint8 *lum_m1 = scanlines->b0;
guint8 *lum = scanlines->bb1;
rounder.uw[0] = 4;
rounder.uw[1] = 4;
@ -109,7 +111,7 @@ deinterlace_line_mmx (GstDeinterlaceMethod * self, GstDeinterlace * parent,
pxor_r2r (mm7, mm7);
movq_m2r (rounder, mm6);
for (; width > 1; width -= 2) {
for (; size > 3; size -= 4) {
movd_m2r (*lum_m4, mm0);
movd_m2r (*lum_m3, mm1);
movd_m2r (*lum_m2, mm2);
@ -140,15 +142,22 @@ deinterlace_line_mmx (GstDeinterlaceMethod * self, GstDeinterlace * parent,
emms ();
/* Handle odd widths */
if (width > 0) {
scanlines->tt1 = lum_m4;
scanlines->t0 = lum_m3;
scanlines->m1 = lum_m2;
scanlines->b0 = lum_m1;
scanlines->bb1 = lum;
if (size > 0)
deinterlace_c (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size);
}
deinterlace_line_c (self, parent, dst, scanlines, width);
}
static void
deinterlace_line_packed_mmx (GstDeinterlaceSimpleMethod * self, guint8 * dst,
const GstDeinterlaceScanlineData * scanlines)
{
const guint8 *lum_m4 = scanlines->tt1;
const guint8 *lum_m3 = scanlines->t0;
const guint8 *lum_m2 = scanlines->m1;
const guint8 *lum_m1 = scanlines->b0;
const guint8 *lum = scanlines->bb1;
gint size = self->parent.row_stride[0];
deinterlace_mmx (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size);
}
#endif
@ -172,12 +181,15 @@ gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass)
#ifdef BUILD_X86_ASM
if (cpu_flags & OIL_IMPL_FLAG_MMX) {
dism_class->interpolate_scanline = deinterlace_line_mmx;
dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_mmx;
dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_mmx;
} else {
dism_class->interpolate_scanline = deinterlace_line_c;
dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_c;
dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_c;
}
#else
dism_class->interpolate_scanline = deinterlace_line_c;
dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_c;
dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_c;
#endif
}

View file

@ -1,7 +1,7 @@
/**
* Weave frames
* Copyright (C) 2002 Billy Biggs <vektor@dumbterm.net>.
* Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* Copyright (C) 2008,2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -28,7 +28,6 @@
# include "config.h"
#endif
#include "_stdint.h"
#include "gstdeinterlace.h"
#include <string.h>
@ -43,23 +42,20 @@
GType gst_deinterlace_method_weave_get_type (void);
typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeave;
typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveClass;
static void
deinterlace_scanline_weave (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_weave_packed (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
oil_memcpy (out, scanlines->m1, parent->row_stride);
oil_memcpy (out, scanlines->m1, self->parent.row_stride[0]);
}
static void
copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace * parent,
guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width)
copy_scanline_packed (GstDeinterlaceSimpleMethod * self, guint8 * out,
const GstDeinterlaceScanlineData * scanlines)
{
oil_memcpy (out, scanlines->m0, parent->row_stride);
oil_memcpy (out, scanlines->m0, self->parent.row_stride[0]);
}
G_DEFINE_TYPE (GstDeinterlaceMethodWeave, gst_deinterlace_method_weave,
@ -77,8 +73,9 @@ gst_deinterlace_method_weave_class_init (GstDeinterlaceMethodWeaveClass * klass)
dim_class->nick = "weave";
dim_class->latency = 0;
dism_class->interpolate_scanline = deinterlace_scanline_weave;
dism_class->copy_scanline = copy_scanline;
dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed;
dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed;
dism_class->copy_scanline_yvyu = copy_scanline_packed;
}
static void

View file

@ -1,7 +1,7 @@
/**
* Weave frames, bottom-field-first.
* Copyright (C) 2003 Billy Biggs <vektor@dumbterm.net>.
* Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* Copyright (C) 2008,2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -28,7 +28,6 @@
# include "config.h"
#endif
#include "_stdint.h"
#include "gstdeinterlace.h"
#include <string.h>
@ -43,27 +42,24 @@
GType gst_deinterlace_method_weave_bff_get_type (void);
typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeaveBFF;
typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveBFFClass;
static void
deinterlace_scanline_weave (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_weave_packed (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
oil_memcpy (out, scanlines->m1, parent->row_stride);
oil_memcpy (out, scanlines->m1, self->parent.row_stride[0]);
}
static void
copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace * parent,
guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width)
copy_scanline_packed (GstDeinterlaceSimpleMethod * self, guint8 * out,
const GstDeinterlaceScanlineData * scanlines)
{
/* FIXME: original code used m2 and m0 but this looks really bad */
if (scanlines->bottom_field) {
oil_memcpy (out, scanlines->bb2, parent->row_stride);
oil_memcpy (out, scanlines->bb2, self->parent.row_stride[0]);
} else {
oil_memcpy (out, scanlines->bb0, parent->row_stride);
oil_memcpy (out, scanlines->bb0, self->parent.row_stride[0]);
}
}
@ -83,8 +79,10 @@ gst_deinterlace_method_weave_bff_class_init (GstDeinterlaceMethodWeaveBFFClass *
dim_class->nick = "weavebff";
dim_class->latency = 0;
dism_class->interpolate_scanline = deinterlace_scanline_weave;
dism_class->copy_scanline = copy_scanline;
dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed;
dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed;
dism_class->copy_scanline_yuy2 = copy_scanline_packed;
dism_class->copy_scanline_yvyu = copy_scanline_packed;
}
static void

View file

@ -1,7 +1,7 @@
/**
* Weave frames, top-field-first.
* Copyright (C) 2003 Billy Biggs <vektor@dumbterm.net>.
* Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
* Copyright (C) 2008,2010 Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -29,7 +29,6 @@
# include "config.h"
#endif
#include "_stdint.h"
#include "gstdeinterlace.h"
#include <string.h>
@ -44,27 +43,24 @@
GType gst_deinterlace_method_weave_tff_get_type (void);
typedef GstDeinterlaceSimpleMethod GstDeinterlaceMethodWeaveTFF;
typedef GstDeinterlaceSimpleMethodClass GstDeinterlaceMethodWeaveTFFClass;
static void
deinterlace_scanline_weave (GstDeinterlaceMethod * self,
GstDeinterlace * parent, guint8 * out,
GstDeinterlaceScanlineData * scanlines, gint width)
deinterlace_scanline_weave_packed (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
oil_memcpy (out, scanlines->m1, parent->row_stride);
oil_memcpy (out, scanlines->m1, self->parent.row_stride[0]);
}
static void
copy_scanline (GstDeinterlaceMethod * self, GstDeinterlace * parent,
guint8 * out, GstDeinterlaceScanlineData * scanlines, gint width)
copy_scanline_packed (GstDeinterlaceSimpleMethod * self,
guint8 * out, const GstDeinterlaceScanlineData * scanlines)
{
/* FIXME: original code used m2 and m0 but this looks really bad */
if (scanlines->bottom_field) {
oil_memcpy (out, scanlines->bb0, parent->row_stride);
oil_memcpy (out, scanlines->bb0, self->parent.row_stride[0]);
} else {
oil_memcpy (out, scanlines->bb2, parent->row_stride);
oil_memcpy (out, scanlines->bb2, self->parent.row_stride[0]);
}
}
@ -84,8 +80,10 @@ gst_deinterlace_method_weave_tff_class_init (GstDeinterlaceMethodWeaveTFFClass *
dim_class->nick = "weavetff";
dim_class->latency = 0;
dism_class->interpolate_scanline = deinterlace_scanline_weave;
dism_class->copy_scanline = copy_scanline;
dism_class->interpolate_scanline_yuy2 = deinterlace_scanline_weave_packed;
dism_class->interpolate_scanline_yvyu = deinterlace_scanline_weave_packed;
dism_class->copy_scanline_yuy2 = copy_scanline_packed;
dism_class->copy_scanline_yvyu = copy_scanline_packed;
}
static void