mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
deinterlace: Refactor deinterlacing as preparation for supporting more color formats
This commit is contained in:
parent
e2eb012a41
commit
3dc7215492
15 changed files with 839 additions and 590 deletions
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
int64_t QW256B;
|
||||
int64_t LastAvg = 0; //interp value from left qword
|
||||
gint64 QW256B;
|
||||
gint64 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..
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue