summaryrefslogtreecommitdiff
path: root/gst/deinterlace/gstdeinterlacemethod.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/deinterlace/gstdeinterlacemethod.c')
-rwxr-xr-xgst/deinterlace/gstdeinterlacemethod.c802
1 files changed, 802 insertions, 0 deletions
diff --git a/gst/deinterlace/gstdeinterlacemethod.c b/gst/deinterlace/gstdeinterlacemethod.c
new file mode 100755
index 0000000..93e77e7
--- /dev/null
+++ b/gst/deinterlace/gstdeinterlacemethod.c
@@ -0,0 +1,802 @@
+/*
+ * GStreamer
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * 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
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstdeinterlacemethod.h"
+
+G_DEFINE_ABSTRACT_TYPE (GstDeinterlaceMethod, gst_deinterlace_method,
+ GST_TYPE_OBJECT);
+
+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);
+ case GST_VIDEO_FORMAT_UYVY:
+ return (klass->deinterlace_frame_uyvy != 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);
+ case GST_VIDEO_FORMAT_AYUV:
+ return (klass->deinterlace_frame_ayuv != NULL);
+ case GST_VIDEO_FORMAT_NV12:
+ return (klass->deinterlace_frame_nv12 != NULL);
+ case GST_VIDEO_FORMAT_NV21:
+ return (klass->deinterlace_frame_nv21 != NULL);
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_xRGB:
+ return (klass->deinterlace_frame_argb != NULL);
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_xBGR:
+ return (klass->deinterlace_frame_abgr != NULL);
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_RGBx:
+ return (klass->deinterlace_frame_rgba != NULL);
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_BGRx:
+ return (klass->deinterlace_frame_bgra != NULL);
+ case GST_VIDEO_FORMAT_RGB:
+ return (klass->deinterlace_frame_rgb != NULL);
+ case GST_VIDEO_FORMAT_BGR:
+ return (klass->deinterlace_frame_bgr != NULL);
+ default:
+ return FALSE;
+ }
+}
+
+void
+gst_deinterlace_method_setup (GstDeinterlaceMethod * self, GstVideoInfo * vinfo)
+{
+ GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+
+ klass->setup (self, vinfo);
+}
+
+static void
+gst_deinterlace_method_setup_impl (GstDeinterlaceMethod * self,
+ GstVideoInfo * vinfo)
+{
+ GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+
+ self->vinfo = vinfo;
+
+ self->deinterlace_frame = NULL;
+
+ if (GST_VIDEO_INFO_FORMAT (self->vinfo) == GST_VIDEO_FORMAT_UNKNOWN)
+ return;
+
+ switch (GST_VIDEO_INFO_FORMAT (self->vinfo)) {
+ 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;
+ case GST_VIDEO_FORMAT_UYVY:
+ self->deinterlace_frame = klass->deinterlace_frame_uyvy;
+ 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;
+ case GST_VIDEO_FORMAT_AYUV:
+ self->deinterlace_frame = klass->deinterlace_frame_ayuv;
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ self->deinterlace_frame = klass->deinterlace_frame_nv12;
+ break;
+ case GST_VIDEO_FORMAT_NV21:
+ self->deinterlace_frame = klass->deinterlace_frame_nv21;
+ break;
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_xRGB:
+ self->deinterlace_frame = klass->deinterlace_frame_argb;
+ break;
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_xBGR:
+ self->deinterlace_frame = klass->deinterlace_frame_abgr;
+ break;
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_RGBx:
+ self->deinterlace_frame = klass->deinterlace_frame_rgba;
+ break;
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_BGRx:
+ self->deinterlace_frame = klass->deinterlace_frame_bgra;
+ break;
+ case GST_VIDEO_FORMAT_RGB:
+ self->deinterlace_frame = klass->deinterlace_frame_rgb;
+ break;
+ case GST_VIDEO_FORMAT_BGR:
+ self->deinterlace_frame = klass->deinterlace_frame_bgr;
+ 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->vinfo = NULL;
+}
+
+void
+gst_deinterlace_method_deinterlace_frame (GstDeinterlaceMethod * self,
+ const GstDeinterlaceField * history, guint history_count,
+ GstVideoFrame * outframe, int cur_field_idx)
+{
+ g_assert (self->deinterlace_frame != NULL);
+ self->deinterlace_frame (self, history, history_count, outframe,
+ cur_field_idx);
+}
+
+gint
+gst_deinterlace_method_get_fields_required (GstDeinterlaceMethod * self)
+{
+ GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+
+ return klass->fields_required;
+}
+
+gint
+gst_deinterlace_method_get_latency (GstDeinterlaceMethod * self)
+{
+ GstDeinterlaceMethodClass *klass = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+
+ return klass->latency;
+}
+
+G_DEFINE_ABSTRACT_TYPE (GstDeinterlaceSimpleMethod,
+ gst_deinterlace_simple_method, GST_TYPE_DEINTERLACE_METHOD);
+
+static gboolean
+gst_deinterlace_simple_method_supported (GstDeinterlaceMethodClass * mklass,
+ GstVideoFormat format, gint width, gint height)
+{
+ 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_ARGB:
+ case GST_VIDEO_FORMAT_xRGB:
+ return (klass->interpolate_scanline_argb != NULL
+ && klass->copy_scanline_argb != NULL);
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_RGBx:
+ return (klass->interpolate_scanline_rgba != NULL
+ && klass->copy_scanline_rgba != NULL);
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_xBGR:
+ return (klass->interpolate_scanline_abgr != NULL
+ && klass->copy_scanline_abgr != NULL);
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_BGRx:
+ return (klass->interpolate_scanline_bgra != NULL
+ && klass->copy_scanline_bgra != NULL);
+ case GST_VIDEO_FORMAT_RGB:
+ return (klass->interpolate_scanline_rgb != NULL
+ && klass->copy_scanline_rgb != NULL);
+ case GST_VIDEO_FORMAT_BGR:
+ return (klass->interpolate_scanline_bgr != NULL
+ && klass->copy_scanline_bgr != NULL);
+ 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);
+ case GST_VIDEO_FORMAT_UYVY:
+ return (klass->interpolate_scanline_uyvy != NULL
+ && klass->copy_scanline_uyvy != NULL);
+ case GST_VIDEO_FORMAT_AYUV:
+ return (klass->interpolate_scanline_ayuv != NULL
+ && klass->copy_scanline_ayuv != NULL);
+ case GST_VIDEO_FORMAT_NV12:
+ return (klass->interpolate_scanline_nv12 != NULL
+ && klass->copy_scanline_nv12 != NULL);
+ case GST_VIDEO_FORMAT_NV21:
+ return (klass->interpolate_scanline_nv21 != NULL
+ && klass->copy_scanline_nv21 != 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;
+ }
+}
+
+static void
+ gst_deinterlace_simple_method_interpolate_scanline_packed
+ (GstDeinterlaceSimpleMethod * self, guint8 * out,
+ const GstDeinterlaceScanlineData * scanlines, guint stride)
+{
+ memcpy (out, scanlines->m1, stride);
+}
+
+static void
+gst_deinterlace_simple_method_copy_scanline_packed (GstDeinterlaceSimpleMethod *
+ self, guint8 * out, const GstDeinterlaceScanlineData * scanlines,
+ guint stride)
+{
+ memcpy (out, scanlines->m0, stride);
+}
+
+static void
+gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod *
+ method, const GstDeinterlaceField * history, guint history_count,
+ GstVideoFrame * outframe, gint cur_field_idx)
+{
+ GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
+#ifndef G_DISABLE_ASSERT
+ GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+#endif
+ GstDeinterlaceScanlineData scanlines;
+ guint cur_field_flags;
+ gint i;
+ gint frame_height, frame_width;
+ GstVideoFrame *framep, *frame0, *frame1, *frame2;
+
+ g_assert (self->interpolate_scanline_packed != NULL);
+ g_assert (self->copy_scanline_packed != NULL);
+
+ frame_height = GST_VIDEO_FRAME_HEIGHT (outframe);
+ frame_width = GST_VIDEO_FRAME_PLANE_STRIDE (outframe, 0);
+
+ frame0 = history[cur_field_idx].frame;
+ frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (frame0, 0));
+ cur_field_flags = history[cur_field_idx].flags;
+
+ framep = (cur_field_idx > 0 ? history[cur_field_idx - 1].frame : NULL);
+ if (framep)
+ frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (framep, 0));
+
+ g_assert (dm_class->fields_required <= 4);
+
+ frame1 =
+ (cur_field_idx + 1 <
+ history_count ? history[cur_field_idx + 1].frame : NULL);
+ if (frame1)
+ frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (frame1, 0));
+
+ frame2 =
+ (cur_field_idx + 2 <
+ history_count ? history[cur_field_idx + 2].frame : NULL);
+ if (frame2)
+ frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (frame2, 0));
+
+#define CLAMP_LOW(i) (((i)<0) ? (i+2) : (i))
+#define CLAMP_HI(i) (((i)>=(frame_height)) ? (i-2) : (i))
+#define LINE(x,i) (((guint8*)GST_VIDEO_FRAME_PLANE_DATA((x),0)) + CLAMP_HI(CLAMP_LOW(i)) * \
+ GST_VIDEO_FRAME_PLANE_STRIDE((x),0))
+#define LINE2(x,i) ((x) ? LINE(x,i) : NULL)
+
+ for (i = 0; i < frame_height; i++) {
+ memset (&scanlines, 0, sizeof (scanlines));
+ scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
+
+ if (!((i & 1) ^ scanlines.bottom_field)) {
+ /* copying */
+ scanlines.tp = LINE2 (framep, i - 1);
+ scanlines.bp = LINE2 (framep, i + 1);
+
+ scanlines.tt0 = LINE2 (frame0, (i - 2 >= 0) ? i - 2 : i);
+ scanlines.m0 = LINE2 (frame0, i);
+ scanlines.bb0 = LINE2 (frame0, (i + 2 < frame_height ? i + 2 : i));
+
+ scanlines.t1 = LINE2 (frame1, i - 1);
+ scanlines.b1 = LINE2 (frame1, i + 1);
+
+ scanlines.tt2 = LINE2 (frame2, (i - 2 >= 0) ? i - 2 : i);
+ scanlines.m2 = LINE2 (frame2, i);
+ scanlines.bb2 = LINE2 (frame2, (i + 2 < frame_height ? i + 2 : i));
+
+ self->copy_scanline_packed (self, LINE (outframe, i), &scanlines,
+ frame_width);
+ } else {
+ /* interpolating */
+ scanlines.ttp = LINE2 (framep, (i - 2 >= 0) ? i - 2 : i);
+ scanlines.mp = LINE2 (framep, i);
+ scanlines.bbp = LINE2 (framep, (i + 2 < frame_height ? i + 2 : i));
+
+ scanlines.t0 = LINE2 (frame0, i - 1);
+ scanlines.b0 = LINE2 (frame0, i + 1);
+
+ scanlines.tt1 = LINE2 (frame1, (i - 2 >= 0) ? i - 2 : i);
+ scanlines.m1 = LINE2 (frame1, i);
+ scanlines.bb1 = LINE2 (frame1, (i + 2 < frame_height ? i + 2 : i));
+
+ scanlines.t2 = LINE2 (frame2, i - 1);
+ scanlines.b2 = LINE2 (frame2, i + 1);
+
+ self->interpolate_scanline_packed (self, LINE (outframe, i), &scanlines,
+ frame_width);
+ }
+#undef LINE
+#undef LINE2
+ }
+}
+
+static void
+ gst_deinterlace_simple_method_interpolate_scanline_planar_y
+ (GstDeinterlaceSimpleMethod * self, guint8 * out,
+ const GstDeinterlaceScanlineData * scanlines, guint size)
+{
+ memcpy (out, scanlines->m1, size);
+}
+
+static void
+gst_deinterlace_simple_method_copy_scanline_planar_y (GstDeinterlaceSimpleMethod
+ * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines, guint
+ size)
+{
+ memcpy (out, scanlines->m0, size);
+}
+
+static void
+ gst_deinterlace_simple_method_interpolate_scanline_planar_u
+ (GstDeinterlaceSimpleMethod * self, guint8 * out,
+ const GstDeinterlaceScanlineData * scanlines, guint size)
+{
+ memcpy (out, scanlines->m1, size);
+}
+
+static void
+gst_deinterlace_simple_method_copy_scanline_planar_u (GstDeinterlaceSimpleMethod
+ * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines, guint
+ size)
+{
+ memcpy (out, scanlines->m0, size);
+}
+
+static void
+ gst_deinterlace_simple_method_interpolate_scanline_planar_v
+ (GstDeinterlaceSimpleMethod * self, guint8 * out,
+ const GstDeinterlaceScanlineData * scanlines, guint size)
+{
+ memcpy (out, scanlines->m1, size);
+}
+
+static void
+gst_deinterlace_simple_method_copy_scanline_planar_v (GstDeinterlaceSimpleMethod
+ * self, guint8 * out, const GstDeinterlaceScanlineData * scanlines, guint
+ size)
+{
+ memcpy (out, scanlines->m0, size);
+}
+
+static void
+ gst_deinterlace_simple_method_deinterlace_frame_planar_plane
+ (GstDeinterlaceSimpleMethod * self, GstVideoFrame * dest,
+ const GstVideoFrame * frame0, const GstVideoFrame * frame1,
+ const GstVideoFrame * frame2, const GstVideoFrame * framep,
+ guint cur_field_flags, gint plane,
+ GstDeinterlaceSimpleMethodFunction copy_scanline,
+ GstDeinterlaceSimpleMethodFunction interpolate_scanline)
+{
+ GstDeinterlaceScanlineData scanlines;
+ gint i;
+ gint frame_height, frame_width;
+
+ frame_height = GST_VIDEO_FRAME_COMP_HEIGHT (dest, plane);
+ frame_width = GST_VIDEO_FRAME_COMP_WIDTH (dest, plane) *
+ GST_VIDEO_FRAME_COMP_PSTRIDE (dest, plane);
+
+ g_assert (interpolate_scanline != NULL);
+ g_assert (copy_scanline != NULL);
+
+#define LINE(x,i) (((guint8*)GST_VIDEO_FRAME_PLANE_DATA((x),plane)) + CLAMP_HI(CLAMP_LOW(i)) * \
+ GST_VIDEO_FRAME_PLANE_STRIDE((x),plane))
+#define LINE2(x,i) ((x) ? LINE(x,i) : NULL)
+
+ for (i = 0; i < frame_height; i++) {
+ memset (&scanlines, 0, sizeof (scanlines));
+ scanlines.bottom_field = (cur_field_flags == PICTURE_INTERLACED_BOTTOM);
+
+ if (!((i & 1) ^ scanlines.bottom_field)) {
+ /* copying */
+ scanlines.tp = LINE2 (framep, i - 1);
+ scanlines.bp = LINE2 (framep, i + 1);
+
+ scanlines.tt0 = LINE2 (frame0, (i - 2 >= 0) ? i - 2 : i);
+ scanlines.m0 = LINE2 (frame0, i);
+ scanlines.bb0 = LINE2 (frame0, (i + 2 < frame_height ? i + 2 : i));
+
+ scanlines.t1 = LINE2 (frame1, i - 1);
+ scanlines.b1 = LINE2 (frame1, i + 1);
+
+ scanlines.tt2 = LINE2 (frame2, (i - 2 >= 0) ? i - 2 : i);
+ scanlines.m2 = LINE2 (frame2, i);
+ scanlines.bb2 = LINE2 (frame2, (i + 2 < frame_height ? i + 2 : i));
+
+ copy_scanline (self, LINE (dest, i), &scanlines, frame_width);
+ } else {
+ /* interpolating */
+ scanlines.ttp = LINE2 (framep, (i - 2 >= 0) ? i - 2 : i);
+ scanlines.mp = LINE2 (framep, i);
+ scanlines.bbp = LINE2 (framep, (i + 2 < frame_height ? i + 2 : i));
+
+ scanlines.t0 = LINE2 (frame0, i - 1);
+ scanlines.b0 = LINE2 (frame0, i + 1);
+
+ scanlines.tt1 = LINE2 (frame1, (i - 2 >= 0) ? i - 2 : i);
+ scanlines.m1 = LINE2 (frame1, i);
+ scanlines.bb1 = LINE2 (frame1, (i + 2 < frame_height ? i + 2 : i));
+
+ scanlines.t2 = LINE2 (frame2, i - 1);
+ scanlines.b2 = LINE2 (frame2, i + 1);
+
+ interpolate_scanline (self, LINE (dest, i), &scanlines, frame_width);
+ }
+#undef LINE
+#undef LINE2
+ }
+}
+
+static void
+gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod *
+ method, const GstDeinterlaceField * history, guint history_count,
+ GstVideoFrame * outframe, gint cur_field_idx)
+{
+ GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
+#ifndef G_DISABLE_ASSERT
+ GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+#endif
+ const GstVideoFrame *frame0, *frame1, *frame2, *framep;
+ guint cur_field_flags = history[cur_field_idx].flags;
+ gint i;
+ 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++) {
+ copy_scanline = self->copy_scanline_planar[i];
+ interpolate_scanline = self->interpolate_scanline_planar[i];
+
+ framep = (cur_field_idx > 0 ? history[cur_field_idx - 1].frame : NULL);
+
+ frame0 = history[cur_field_idx].frame;
+
+ g_assert (dm_class->fields_required <= 4);
+
+ frame1 =
+ (cur_field_idx + 1 <
+ history_count ? history[cur_field_idx + 1].frame : NULL);
+ frame2 =
+ (cur_field_idx + 2 <
+ history_count ? history[cur_field_idx + 2].frame : NULL);
+
+ gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self,
+ outframe, frame0, frame1, frame2, framep, cur_field_flags, i,
+ copy_scanline, interpolate_scanline);
+ }
+}
+
+static void
+gst_deinterlace_simple_method_deinterlace_frame_nv12 (GstDeinterlaceMethod *
+ method, const GstDeinterlaceField * history, guint history_count,
+ GstVideoFrame * outframe, gint cur_field_idx)
+{
+ GstDeinterlaceSimpleMethod *self = GST_DEINTERLACE_SIMPLE_METHOD (method);
+#ifndef G_DISABLE_ASSERT
+ GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self);
+#endif
+ const GstVideoFrame *frame0, *frame1, *frame2, *framep;
+ guint cur_field_flags = history[cur_field_idx].flags;
+ gint i;
+
+ g_assert (self->interpolate_scanline_packed != NULL);
+ g_assert (self->copy_scanline_packed != NULL);
+
+ for (i = 0; i < 2; i++) {
+ framep = (cur_field_idx > 0 ? history[cur_field_idx - 1].frame : NULL);
+
+ frame0 = history[cur_field_idx].frame;
+
+ g_assert (dm_class->fields_required <= 4);
+
+ frame1 =
+ (cur_field_idx + 1 <
+ history_count ? history[cur_field_idx + 1].frame : NULL);
+ frame2 =
+ (cur_field_idx + 2 <
+ history_count ? history[cur_field_idx + 2].frame : NULL);
+
+ gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self,
+ outframe, frame0, frame1, frame2, framep, cur_field_flags, i,
+ self->copy_scanline_packed, self->interpolate_scanline_packed);
+ }
+}
+
+static void
+gst_deinterlace_simple_method_setup (GstDeinterlaceMethod * method,
+ GstVideoInfo * vinfo)
+{
+ 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, vinfo);
+
+ 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 (GST_VIDEO_INFO_FORMAT (vinfo) == GST_VIDEO_FORMAT_UNKNOWN)
+ return;
+
+ switch (GST_VIDEO_INFO_FORMAT (vinfo)) {
+ 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;
+ case GST_VIDEO_FORMAT_UYVY:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_uyvy;
+ self->copy_scanline_packed = klass->copy_scanline_uyvy;
+ break;
+ case GST_VIDEO_FORMAT_AYUV:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_ayuv;
+ self->copy_scanline_packed = klass->copy_scanline_ayuv;
+ break;
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_xRGB:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_argb;
+ self->copy_scanline_packed = klass->copy_scanline_argb;
+ break;
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_xBGR:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_abgr;
+ self->copy_scanline_packed = klass->copy_scanline_abgr;
+ break;
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_RGBx:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_rgba;
+ self->copy_scanline_packed = klass->copy_scanline_rgba;
+ break;
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_BGRx:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_bgra;
+ self->copy_scanline_packed = klass->copy_scanline_bgra;
+ break;
+ case GST_VIDEO_FORMAT_RGB:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_rgb;
+ self->copy_scanline_packed = klass->copy_scanline_rgb;
+ break;
+ case GST_VIDEO_FORMAT_BGR:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_bgr;
+ self->copy_scanline_packed = klass->copy_scanline_bgr;
+ break;
+ case GST_VIDEO_FORMAT_NV12:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_nv12;
+ self->copy_scanline_packed = klass->copy_scanline_nv12;
+ break;
+ case GST_VIDEO_FORMAT_NV21:
+ self->interpolate_scanline_packed = klass->interpolate_scanline_nv21;
+ self->copy_scanline_packed = klass->copy_scanline_nv21;
+ 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)
+{
+ GstDeinterlaceMethodClass *dm_class = (GstDeinterlaceMethodClass *) klass;
+
+ dm_class->deinterlace_frame_ayuv =
+ gst_deinterlace_simple_method_deinterlace_frame_packed;
+ 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->deinterlace_frame_uyvy =
+ gst_deinterlace_simple_method_deinterlace_frame_packed;
+ dm_class->deinterlace_frame_argb =
+ gst_deinterlace_simple_method_deinterlace_frame_packed;
+ dm_class->deinterlace_frame_abgr =
+ gst_deinterlace_simple_method_deinterlace_frame_packed;
+ dm_class->deinterlace_frame_rgba =
+ gst_deinterlace_simple_method_deinterlace_frame_packed;
+ dm_class->deinterlace_frame_bgra =
+ gst_deinterlace_simple_method_deinterlace_frame_packed;
+ dm_class->deinterlace_frame_rgb =
+ gst_deinterlace_simple_method_deinterlace_frame_packed;
+ dm_class->deinterlace_frame_bgr =
+ 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->deinterlace_frame_nv12 =
+ gst_deinterlace_simple_method_deinterlace_frame_nv12;
+ dm_class->deinterlace_frame_nv21 =
+ gst_deinterlace_simple_method_deinterlace_frame_nv12;
+ dm_class->fields_required = 2;
+ dm_class->setup = gst_deinterlace_simple_method_setup;
+ dm_class->supported = gst_deinterlace_simple_method_supported;
+
+ 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;
+ klass->interpolate_scanline_ayuv =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_ayuv =
+ gst_deinterlace_simple_method_copy_scanline_packed;
+ klass->interpolate_scanline_uyvy =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_uyvy =
+ gst_deinterlace_simple_method_copy_scanline_packed;
+ klass->interpolate_scanline_nv12 =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_nv12 =
+ gst_deinterlace_simple_method_copy_scanline_packed;
+
+ klass->interpolate_scanline_argb =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_argb =
+ gst_deinterlace_simple_method_copy_scanline_packed;
+ klass->interpolate_scanline_abgr =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_abgr =
+ gst_deinterlace_simple_method_copy_scanline_packed;
+
+ klass->interpolate_scanline_rgba =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_rgba =
+ gst_deinterlace_simple_method_copy_scanline_packed;
+ klass->interpolate_scanline_bgra =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_bgra =
+ gst_deinterlace_simple_method_copy_scanline_packed;
+ klass->interpolate_scanline_rgb =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_rgb = gst_deinterlace_simple_method_copy_scanline_packed;
+ klass->interpolate_scanline_bgr =
+ gst_deinterlace_simple_method_interpolate_scanline_packed;
+ klass->copy_scanline_bgr = 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
+gst_deinterlace_simple_method_init (GstDeinterlaceSimpleMethod * self)
+{
+}