From 03a8379e209c6881aa9c0c71c0c60e72fbd71ef7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Sat, 24 Apr 2010 13:58:03 +0200 Subject: [PATCH] deinterlace: Add support for Y444, Y42B, I420, YV12 and Y41B The vfir method supports them and will be used until something else supports it. --- gst/deinterlace/gstdeinterlace.c | 8 +- gst/deinterlace/gstdeinterlacemethod.c | 306 ++++++++++++++++++++++++++++++++- gst/deinterlace/gstdeinterlacemethod.h | 30 +++- gst/deinterlace/tvtime/vfir.c | 93 ++++++++++ 4 files changed, 423 insertions(+), 14 deletions(-) diff --git a/gst/deinterlace/gstdeinterlace.c b/gst/deinterlace/gstdeinterlace.c index 0f655b7..b9023a1 100644 --- a/gst/deinterlace/gstdeinterlace.c +++ b/gst/deinterlace/gstdeinterlace.c @@ -156,14 +156,18 @@ static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2") ";" - GST_VIDEO_CAPS_YUV ("YVYU")) + GST_VIDEO_CAPS_YUV ("YVYU") ";" GST_VIDEO_CAPS_YUV ("I420") ";" + GST_VIDEO_CAPS_YUV ("YV12") ";" GST_VIDEO_CAPS_YUV ("Y444") ";" + GST_VIDEO_CAPS_YUV ("Y42B") ";" GST_VIDEO_CAPS_YUV ("Y41B")) ); static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2") ";" - GST_VIDEO_CAPS_YUV ("YVYU")) + GST_VIDEO_CAPS_YUV ("YVYU") ";" GST_VIDEO_CAPS_YUV ("I420") ";" + GST_VIDEO_CAPS_YUV ("YV12") ";" GST_VIDEO_CAPS_YUV ("Y444") ";" + GST_VIDEO_CAPS_YUV ("Y42B") ";" GST_VIDEO_CAPS_YUV ("Y41B")) ); static void gst_deinterlace_finalize (GObject * self); diff --git a/gst/deinterlace/gstdeinterlacemethod.c b/gst/deinterlace/gstdeinterlacemethod.c index 2d5f5f6..6db1cad 100644 --- a/gst/deinterlace/gstdeinterlacemethod.c +++ b/gst/deinterlace/gstdeinterlacemethod.c @@ -58,6 +58,16 @@ gst_deinterlace_method_supported_impl (GstDeinterlaceMethodClass * klass, return (klass->deinterlace_frame_yuy2 != NULL); case GST_VIDEO_FORMAT_YVYU: return (klass->deinterlace_frame_yvyu != NULL); + case GST_VIDEO_FORMAT_I420: + return (klass->deinterlace_frame_i420 != NULL); + case GST_VIDEO_FORMAT_YV12: + return (klass->deinterlace_frame_yv12 != NULL); + case GST_VIDEO_FORMAT_Y444: + return (klass->deinterlace_frame_y444 != NULL); + case GST_VIDEO_FORMAT_Y42B: + return (klass->deinterlace_frame_y42b != NULL); + case GST_VIDEO_FORMAT_Y41B: + return (klass->deinterlace_frame_y41b != NULL); default: return FALSE; } @@ -104,6 +114,21 @@ gst_deinterlace_method_setup_impl (GstDeinterlaceMethod * self, case GST_VIDEO_FORMAT_YVYU: self->deinterlace_frame = klass->deinterlace_frame_yvyu; break; + case GST_VIDEO_FORMAT_I420: + self->deinterlace_frame = klass->deinterlace_frame_i420; + break; + case GST_VIDEO_FORMAT_YV12: + self->deinterlace_frame = klass->deinterlace_frame_yv12; + break; + case GST_VIDEO_FORMAT_Y444: + self->deinterlace_frame = klass->deinterlace_frame_y444; + break; + case GST_VIDEO_FORMAT_Y42B: + self->deinterlace_frame = klass->deinterlace_frame_y42b; + break; + case GST_VIDEO_FORMAT_Y41B: + self->deinterlace_frame = klass->deinterlace_frame_y41b; + break; default: self->deinterlace_frame = NULL; break; @@ -170,6 +195,17 @@ gst_deinterlace_simple_method_supported (GstDeinterlaceMethodClass * mklass, case GST_VIDEO_FORMAT_YVYU: return (klass->interpolate_scanline_yvyu != NULL && klass->copy_scanline_yvyu != NULL); + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y41B: + return (klass->interpolate_scanline_planar_y != NULL + && klass->copy_scanline_planar_y != NULL && + klass->interpolate_scanline_planar_u != NULL + && klass->copy_scanline_planar_u != NULL && + klass->interpolate_scanline_planar_v != NULL + && klass->copy_scanline_planar_v != NULL); default: return FALSE; } @@ -199,7 +235,7 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * 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; + const guint8 *field0 = NULL, *field1 = NULL, *field2 = NULL, *field3 = NULL; gint cur_field_idx = history_count - dm_class->fields_required; guint cur_field_flags = history[cur_field_idx].flags; gint line; @@ -214,7 +250,7 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * if (history[cur_field_idx].flags & PICTURE_INTERLACED_BOTTOM) field0 += row_stride; - g_return_if_fail (dm_class->fields_required <= 4); + g_assert (dm_class->fields_required <= 4); if (dm_class->fields_required >= 2) { field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf); @@ -234,7 +270,6 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * field3 += row_stride; } - if (cur_field_flags == PICTURE_INTERLACED_BOTTOM) { /* double the first scanline of the bottom field */ oil_memcpy (out, field0, row_stride); @@ -329,6 +364,222 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * } static void + gst_deinterlace_simple_method_interpolate_scanline_planar_y + (GstDeinterlaceSimpleMethod * self, guint8 * out, + const GstDeinterlaceScanlineData * scanlines) +{ + oil_memcpy (out, scanlines->m1, self->parent.row_stride[0]); +} + +static void +gst_deinterlace_simple_method_copy_scanline_planar_y (GstDeinterlaceSimpleMethod + * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) +{ + oil_memcpy (out, scanlines->m0, self->parent.row_stride[0]); +} + +static void + gst_deinterlace_simple_method_interpolate_scanline_planar_u + (GstDeinterlaceSimpleMethod * self, guint8 * out, + const GstDeinterlaceScanlineData * scanlines) +{ + oil_memcpy (out, scanlines->m1, self->parent.row_stride[1]); +} + +static void +gst_deinterlace_simple_method_copy_scanline_planar_u (GstDeinterlaceSimpleMethod + * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) +{ + oil_memcpy (out, scanlines->m0, self->parent.row_stride[1]); +} + +static void + gst_deinterlace_simple_method_interpolate_scanline_planar_v + (GstDeinterlaceSimpleMethod * self, guint8 * out, + const GstDeinterlaceScanlineData * scanlines) +{ + oil_memcpy (out, scanlines->m1, self->parent.row_stride[2]); +} + +static void +gst_deinterlace_simple_method_copy_scanline_planar_v (GstDeinterlaceSimpleMethod + * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines) +{ + oil_memcpy (out, scanlines->m0, self->parent.row_stride[2]); +} + +static void + gst_deinterlace_simple_method_deinterlace_frame_planar_plane + (GstDeinterlaceSimpleMethod * self, guint8 * out, const guint8 * field0, + const guint8 * field1, const guint8 * field2, const guint8 * field3, + guint cur_field_flags, + gint plane, GstDeinterlaceSimpleMethodFunction copy_scanline, + GstDeinterlaceSimpleMethodFunction interpolate_scanline) +{ + GstDeinterlaceScanlineData scanlines; + gint line; + gint field_height = self->parent.height[plane] / 2; + gint row_stride = self->parent.row_stride[plane]; + gint field_stride = self->parent.row_stride[plane] * 2; + + g_assert (interpolate_scanline != NULL); + g_assert (copy_scanline != NULL); + + if (cur_field_flags == PICTURE_INTERLACED_BOTTOM) { + /* double the first scanline of the bottom field */ + oil_memcpy (out, field0, row_stride); + out += row_stride; + } + + oil_memcpy (out, field0, row_stride); + out += row_stride; + + 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 + field_stride; + + if (field1 != NULL) { + scanlines.tt1 = field1; + scanlines.m1 = field1 + field_stride; + scanlines.bb1 = field1 + field_stride * 2; + field1 += field_stride; + } + + if (field2 != NULL) { + scanlines.t2 = field2; + scanlines.b2 = field2 + field_stride; + } + + if (field3 != NULL) { + scanlines.tt3 = field3; + 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 == field_height) { + scanlines.bb1 = scanlines.tt1; + scanlines.bb3 = scanlines.tt3; + } + + interpolate_scanline (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 + field_stride; + scanlines.bb0 = field0 + field_stride * 2; + field0 += field_stride; + + if (field1 != NULL) { + scanlines.t1 = field1; + scanlines.b1 = field1 + field_stride; + } + + if (field2 != NULL) { + scanlines.tt2 = field2; + scanlines.m2 = field2 + field_stride; + scanlines.bb2 = field2 + field_stride * 2; + field2 += field_stride; + } + + if (field3 != NULL) { + scanlines.t3 = field3; + scanlines.b3 = field3 + field_stride; + } + + /* set valid data for corner cases */ + if (line == field_height) { + scanlines.bb0 = scanlines.tt0; + scanlines.b1 = scanlines.t1; + scanlines.bb2 = scanlines.tt2; + scanlines.b3 = scanlines.t3; + } + + copy_scanline (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, row_stride); + } +} + +static void +gst_deinterlace_simple_method_deinterlace_frame_planar (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); + guint8 *out; + const guint8 *field0 = NULL, *field1 = NULL, *field2 = NULL, *field3 = NULL; + gint cur_field_idx = history_count - dm_class->fields_required; + guint cur_field_flags = history[cur_field_idx].flags; + gint i, row_stride, offset; + GstDeinterlaceSimpleMethodFunction copy_scanline; + GstDeinterlaceSimpleMethodFunction interpolate_scanline; + + g_assert (self->interpolate_scanline_planar[0] != NULL); + g_assert (self->interpolate_scanline_planar[1] != NULL); + g_assert (self->interpolate_scanline_planar[2] != NULL); + g_assert (self->copy_scanline_planar[0] != NULL); + g_assert (self->copy_scanline_planar[1] != NULL); + g_assert (self->copy_scanline_planar[2] != NULL); + + for (i = 0; i < 3; i++) { + row_stride = self->parent.row_stride[i]; + offset = self->parent.offset[i]; + copy_scanline = self->copy_scanline_planar[i]; + interpolate_scanline = self->interpolate_scanline_planar[i]; + + out = GST_BUFFER_DATA (outbuf) + offset; + + field0 = GST_BUFFER_DATA (history[cur_field_idx].buf) + offset; + if (history[cur_field_idx].flags & PICTURE_INTERLACED_BOTTOM) + field0 += row_stride; + + g_assert (dm_class->fields_required <= 4); + + if (dm_class->fields_required >= 2) { + field1 = GST_BUFFER_DATA (history[cur_field_idx + 1].buf) + offset; + 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) + offset; + 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) + offset; + if (history[cur_field_idx + 3].flags & PICTURE_INTERLACED_BOTTOM) + field3 += row_stride; + } + + + gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, out, + field0, field1, field2, field3, cur_field_flags, i, copy_scanline, + interpolate_scanline); + } +} + +static void gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method, GstVideoFormat format, gint width, gint height) { @@ -343,6 +594,13 @@ gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method, self->interpolate_scanline_packed = NULL; self->copy_scanline_packed = NULL; + self->interpolate_scanline_planar[0] = NULL; + self->interpolate_scanline_planar[1] = NULL; + self->interpolate_scanline_planar[2] = NULL; + self->copy_scanline_planar[0] = NULL; + self->copy_scanline_planar[1] = NULL; + self->copy_scanline_planar[2] = NULL; + if (format == GST_VIDEO_FORMAT_UNKNOWN) return; @@ -355,14 +613,29 @@ gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method, self->interpolate_scanline_packed = klass->interpolate_scanline_yvyu; self->copy_scanline_packed = klass->copy_scanline_yvyu; break; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y41B: + self->interpolate_scanline_planar[0] = + klass->interpolate_scanline_planar_y; + self->copy_scanline_planar[0] = klass->copy_scanline_planar_y; + self->interpolate_scanline_planar[1] = + klass->interpolate_scanline_planar_u; + self->copy_scanline_planar[1] = klass->copy_scanline_planar_u; + self->interpolate_scanline_planar[2] = + klass->interpolate_scanline_planar_v; + self->copy_scanline_planar[2] = klass->copy_scanline_planar_v; + break; default: break; } } static void -gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass * - klass) +gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass + * klass) { GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass; @@ -370,6 +643,16 @@ gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass * gst_deinterlace_simple_method_deinterlace_frame_packed; dm_class->deinterlace_frame_yvyu = gst_deinterlace_simple_method_deinterlace_frame_packed; + dm_class->deinterlace_frame_i420 = + gst_deinterlace_simple_method_deinterlace_frame_planar; + dm_class->deinterlace_frame_yv12 = + gst_deinterlace_simple_method_deinterlace_frame_planar; + dm_class->deinterlace_frame_y444 = + gst_deinterlace_simple_method_deinterlace_frame_planar; + dm_class->deinterlace_frame_y42b = + gst_deinterlace_simple_method_deinterlace_frame_planar; + dm_class->deinterlace_frame_y41b = + gst_deinterlace_simple_method_deinterlace_frame_planar; dm_class->fields_required = 2; dm_class->setup = gst_deinterlace_simple_method_setup; dm_class->supported = gst_deinterlace_simple_method_supported; @@ -382,6 +665,19 @@ gst_deinterlace_simple_method_class_init (GstDeinterlaceSimpleMethodClass * gst_deinterlace_simple_method_interpolate_scanline_packed; klass->copy_scanline_yvyu = gst_deinterlace_simple_method_copy_scanline_packed; + + klass->interpolate_scanline_planar_y = + gst_deinterlace_simple_method_interpolate_scanline_planar_y; + klass->copy_scanline_planar_y = + gst_deinterlace_simple_method_copy_scanline_planar_y; + klass->interpolate_scanline_planar_u = + gst_deinterlace_simple_method_interpolate_scanline_planar_u; + klass->copy_scanline_planar_u = + gst_deinterlace_simple_method_copy_scanline_planar_u; + klass->interpolate_scanline_planar_v = + gst_deinterlace_simple_method_interpolate_scanline_planar_v; + klass->copy_scanline_planar_v = + gst_deinterlace_simple_method_copy_scanline_planar_v; } static void diff --git a/gst/deinterlace/gstdeinterlacemethod.h b/gst/deinterlace/gstdeinterlacemethod.h index e9212b6..4ae85c1 100644 --- a/gst/deinterlace/gstdeinterlacemethod.h +++ b/gst/deinterlace/gstdeinterlacemethod.h @@ -92,6 +92,11 @@ struct _GstDeinterlaceMethodClass { GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_yuy2; GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_yvyu; + GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_i420; + GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_yv12; + GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_y444; + GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_y42b; + GstDeinterlaceMethodDeinterlaceFunction deinterlace_frame_y41b; const gchar *name; const gchar *nick; @@ -153,23 +158,34 @@ struct _GstDeinterlaceScanlineData { * All other values are NULL. */ -typedef void (*GstDeinterlaceSimpleMethodPackedFunction) (GstDeinterlaceSimpleMethod *self, guint8 *out, const GstDeinterlaceScanlineData *scanlines); +typedef void (*GstDeinterlaceSimpleMethodFunction) (GstDeinterlaceSimpleMethod *self, guint8 *out, const GstDeinterlaceScanlineData *scanlines); struct _GstDeinterlaceSimpleMethod { GstDeinterlaceMethod parent; - GstDeinterlaceSimpleMethodPackedFunction interpolate_scanline_packed; - GstDeinterlaceSimpleMethodPackedFunction copy_scanline_packed; + GstDeinterlaceSimpleMethodFunction interpolate_scanline_packed; + GstDeinterlaceSimpleMethodFunction copy_scanline_packed; + + GstDeinterlaceSimpleMethodFunction interpolate_scanline_planar[3]; + GstDeinterlaceSimpleMethodFunction copy_scanline_planar[3]; }; struct _GstDeinterlaceSimpleMethodClass { GstDeinterlaceMethodClass parent_class; /* Packed formats */ - GstDeinterlaceSimpleMethodPackedFunction interpolate_scanline_yuy2; - GstDeinterlaceSimpleMethodPackedFunction copy_scanline_yuy2; - GstDeinterlaceSimpleMethodPackedFunction interpolate_scanline_yvyu; - GstDeinterlaceSimpleMethodPackedFunction copy_scanline_yvyu; + GstDeinterlaceSimpleMethodFunction interpolate_scanline_yuy2; + GstDeinterlaceSimpleMethodFunction copy_scanline_yuy2; + GstDeinterlaceSimpleMethodFunction interpolate_scanline_yvyu; + GstDeinterlaceSimpleMethodFunction copy_scanline_yvyu; + + /* Planar formats */ + GstDeinterlaceSimpleMethodFunction copy_scanline_planar_y; + GstDeinterlaceSimpleMethodFunction interpolate_scanline_planar_y; + GstDeinterlaceSimpleMethodFunction copy_scanline_planar_u; + GstDeinterlaceSimpleMethodFunction interpolate_scanline_planar_u; + GstDeinterlaceSimpleMethodFunction copy_scanline_planar_v; + GstDeinterlaceSimpleMethodFunction interpolate_scanline_planar_v; }; GType gst_deinterlace_simple_method_get_type (void); diff --git a/gst/deinterlace/tvtime/vfir.c b/gst/deinterlace/tvtime/vfir.c index f901c6d..7a4824c 100644 --- a/gst/deinterlace/tvtime/vfir.c +++ b/gst/deinterlace/tvtime/vfir.c @@ -96,6 +96,48 @@ deinterlace_line_packed_c (GstDeinterlaceSimpleMethod * self, guint8 * dst, deinterlace_c (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); } +static void +deinterlace_line_planar_y_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); +} + +static void +deinterlace_line_planar_u_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[1]; + + deinterlace_c (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); +} + +static void +deinterlace_line_planar_v_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[2]; + + deinterlace_c (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); +} + #ifdef BUILD_X86_ASM #include "mmx.h" static void @@ -159,6 +201,48 @@ deinterlace_line_packed_mmx (GstDeinterlaceSimpleMethod * self, guint8 * dst, deinterlace_mmx (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); } + +static void +deinterlace_line_planar_y_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); +} + +static void +deinterlace_line_planar_u_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[1]; + + deinterlace_mmx (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); +} + +static void +deinterlace_line_planar_v_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[2]; + + deinterlace_mmx (dst, lum_m4, lum_m3, lum_m2, lum_m1, lum, size); +} #endif G_DEFINE_TYPE (GstDeinterlaceMethodVFIR, gst_deinterlace_method_vfir, @@ -183,13 +267,22 @@ gst_deinterlace_method_vfir_class_init (GstDeinterlaceMethodVFIRClass * klass) if (cpu_flags & OIL_IMPL_FLAG_MMX) { dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_mmx; dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_mmx; + dism_class->interpolate_scanline_planar_y = deinterlace_line_planar_y_mmx; + dism_class->interpolate_scanline_planar_u = deinterlace_line_planar_u_mmx; + dism_class->interpolate_scanline_planar_v = deinterlace_line_planar_v_mmx; } else { dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_c; dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_c; + dism_class->interpolate_scanline_planar_y = deinterlace_line_planar_y_c; + dism_class->interpolate_scanline_planar_u = deinterlace_line_planar_u_c; + dism_class->interpolate_scanline_planar_v = deinterlace_line_planar_v_c; } #else dism_class->interpolate_scanline_yuy2 = deinterlace_line_packed_c; dism_class->interpolate_scanline_yvyu = deinterlace_line_packed_c; + dism_class->interpolate_scanline_planar_y = deinterlace_line_planar_y_c; + dism_class->interpolate_scanline_planar_u = deinterlace_line_planar_u_c; + dism_class->interpolate_scanline_planar_v = deinterlace_line_planar_v_c; #endif } -- 2.7.4