[Thoggen-cvs] SF.net SVN: thoggen: [229] trunk/thoggen
Status: Beta
Brought to you by:
tp-m
From: <tp...@us...> - 2006-08-23 23:21:27
|
Revision: 229 Author: tp-m Date: 2006-08-23 16:21:13 -0700 (Wed, 23 Aug 2006) ViewCVS: http://svn.sourceforge.net/thoggen/?rev=229&view=rev Log Message: ----------- * src/gst-plugins/Makefile.am: * src/gst-plugins/th-deinterlace.c: * src/gst-plugins/th-deinterlace.h: * src/gst-plugins/th-plugins.c: (plugin_init): Port the fairly basic deinterlacer from 0.8, it's better than nothing at all. * src/th-job.c: (job_create_pipeline): Use deinterlacer. Modified Paths: -------------- trunk/thoggen/ChangeLog trunk/thoggen/src/gst-plugins/Makefile.am trunk/thoggen/src/gst-plugins/th-plugins.c trunk/thoggen/src/th-job.c Added Paths: ----------- trunk/thoggen/src/gst-plugins/th-deinterlace.c trunk/thoggen/src/gst-plugins/th-deinterlace.h Modified: trunk/thoggen/ChangeLog =================================================================== --- trunk/thoggen/ChangeLog 2006-07-19 17:22:18 UTC (rev 228) +++ trunk/thoggen/ChangeLog 2006-08-23 23:21:13 UTC (rev 229) @@ -1,3 +1,17 @@ +2006-08-24 Tim-Philipp Müller <tim at centricular dot net> + + * src/gst-plugins/Makefile.am: + * src/gst-plugins/th-deinterlace.c: + * src/gst-plugins/th-deinterlace.h: + * src/gst-plugins/th-plugins.c: + (plugin_init): + Port the fairly basic deinterlacer from 0.8, it's + better than nothing at all. + + * src/th-job.c: + (job_create_pipeline): + Use deinterlacer. + 2006-07-19 Tim-Philipp Müller <tim at centricular dot net> * src/Makefile.am: Modified: trunk/thoggen/src/gst-plugins/Makefile.am =================================================================== --- trunk/thoggen/src/gst-plugins/Makefile.am 2006-07-19 17:22:18 UTC (rev 228) +++ trunk/thoggen/src/gst-plugins/Makefile.am 2006-08-23 23:21:13 UTC (rev 229) @@ -15,6 +15,8 @@ libthoggenplugins_a_SOURCES = \ th-pixbufsink.c \ th-pixbufsink.h \ + th-deinterlace.c \ + th-deinterlace.h \ th-plugins.c \ th-plugins.h Added: trunk/thoggen/src/gst-plugins/th-deinterlace.c =================================================================== --- trunk/thoggen/src/gst-plugins/th-deinterlace.c (rev 0) +++ trunk/thoggen/src/gst-plugins/th-deinterlace.c 2006-08-23 23:21:13 UTC (rev 229) @@ -0,0 +1,357 @@ +/* Thoggen deinterlace plugin + * Copyright (C) 1999 Erik Walthinsen <om...@cs...> + * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net> + * + * (GStreamer-0.10 port of the GStreamer-0.8 deinterlace plugin) + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* based on the Area Based Deinterlacer (for RGB frames) */ +/* (a VirtualDub filter) from Gunnar Thalin <gu...@ho...> */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> +#include "th-deinterlace.h" +#include <gst/video/video.h> + +/* these macros are adapted from videotestsrc, paint_setup_I420() */ +#define GST_VIDEO_I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width)) +#define GST_VIDEO_I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2) +#define GST_VIDEO_I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(GST_VIDEO_I420_Y_ROWSTRIDE(width)))/2) + +#define GST_VIDEO_I420_Y_OFFSET(w,h) (0) +#define GST_VIDEO_I420_U_OFFSET(w,h) (GST_VIDEO_I420_Y_OFFSET(w,h)+(GST_VIDEO_I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h))) +#define GST_VIDEO_I420_V_OFFSET(w,h) (GST_VIDEO_I420_U_OFFSET(w,h)+(GST_VIDEO_I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) + +#define GST_VIDEO_I420_SIZE(w,h) (GST_VIDEO_I420_V_OFFSET(w,h)+(GST_VIDEO_I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) + +/* elementfactory information */ +static const GstElementDetails deinterlace_details = +GST_ELEMENT_DETAILS ("Deinterlace", + "Filter/Effect/Video", + "Deinterlace video", + "Wim Taymans <wim...@ch...>"); + +enum +{ + ARG_0, + ARG_DI_ONLY, + ARG_BLEND, + ARG_THRESHOLD, + ARG_EDGE_DETECT +}; + +static GstStaticPadTemplate src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) + ); + +static GstStaticPadTemplate sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) + ); + +GST_BOILERPLATE (ThDeinterlace, th_deinterlace, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM); + +static void th_deinterlace_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void th_deinterlace_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static GstFlowReturn th_deinterlace_transform_ip (GstBaseTransform * trans, + GstBuffer *buf); +static gboolean th_deinterlace_stop (GstBaseTransform * trans); +static gboolean th_deinterlace_set_caps (GstBaseTransform * trans, + GstCaps * incaps, GstCaps * outcaps); + +static void +th_deinterlace_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); + + gst_element_class_set_details (element_class, &deinterlace_details); +} + +static void +th_deinterlace_class_init (ThDeinterlaceClass * klass) +{ + GObjectClass *gobject_class; + GstBaseTransformClass *basetransform_class; + + gobject_class = (GObjectClass *) klass; + basetransform_class = (GstBaseTransformClass *) klass; + + gobject_class->set_property = th_deinterlace_set_property; + gobject_class->get_property = th_deinterlace_get_property; + + g_object_class_install_property (gobject_class, ARG_DI_ONLY, + g_param_spec_boolean ("di-area-only", "di-area-only", "di-area-only", + TRUE, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_BLEND, + g_param_spec_boolean ("blend", "blend", "blend", TRUE, + G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_THRESHOLD, + g_param_spec_int ("threshold", "threshold", "threshold", G_MININT, + G_MAXINT, 0, G_PARAM_READWRITE)); + g_object_class_install_property (gobject_class, ARG_EDGE_DETECT, + g_param_spec_int ("edge-detect", "edge-detect", "edge-detect", G_MININT, + G_MAXINT, 0, G_PARAM_READWRITE)); + + basetransform_class->transform_ip = + GST_DEBUG_FUNCPTR (th_deinterlace_transform_ip); + basetransform_class->stop = + GST_DEBUG_FUNCPTR (th_deinterlace_stop); + basetransform_class->set_caps = + GST_DEBUG_FUNCPTR (th_deinterlace_set_caps); +} + +static void +th_deinterlace_init (ThDeinterlace * filter, ThDeinterlaceClass * klass) +{ + filter->show_deinterlaced_area_only = FALSE; + filter->blend = FALSE; + /*filter->threshold_blend = 0; */ + filter->threshold = 50; + filter->edge_detect = 25; + + filter->src = NULL; + filter->picsize = 0; +} + +static gboolean +th_deinterlace_stop (GstBaseTransform * trans) +{ + ThDeinterlace *filter; + + filter = TH_DEINTERLACE (trans); + + g_free (filter->src); + filter->src = NULL; + filter->picsize = 0; + filter->width = 0; + filter->height = 0; + + return TRUE; +} + +static gboolean +th_deinterlace_set_caps (GstBaseTransform * trans, GstCaps * incaps, + GstCaps * outcaps) +{ + ThDeinterlace *filter; + GstStructure *s; + + filter = TH_DEINTERLACE (trans); + + g_assert (gst_caps_is_equal_fixed (incaps, outcaps)); + + s = gst_caps_get_structure (incaps, 0); + gst_structure_get_int (s, "width", &filter->width); + gst_structure_get_int (s, "height", &filter->height); + + GST_LOG_OBJECT (filter, "width x height = %d x %d", filter->width, + filter->height); + + if (filter->picsize != GST_VIDEO_I420_SIZE (filter->width, filter->height)) { + filter->picsize = GST_VIDEO_I420_SIZE (filter->width, filter->height); + g_free (filter->src); /* free + alloc avoids memcpy */ + filter->src = g_malloc0 (filter->picsize); + GST_LOG_OBJECT (filter, "temp buffer size %d", filter->picsize); + } + + return TRUE; +} + +static GstFlowReturn +th_deinterlace_transform_ip (GstBaseTransform * trans, GstBuffer *buf) +{ + ThDeinterlace *filter; + gboolean bShowDeinterlacedAreaOnly; + gint y0, y1, y2, y3; + guchar *psrc1, *psrc2, *psrc3, *pdst1, *yuvptr, *src; + gint iInterlaceValue0, iInterlaceValue1, iInterlaceValue2; + gint x, y; + gint y_line; + guchar *y_dst, *y_src; + gboolean bBlend; + gint iThreshold; + gint iEdgeDetect; + gint width, height; + + /* g_assert (gst_buffer_is_writable (buf)); */ + + filter = TH_DEINTERLACE (trans); + + bBlend = filter->blend; + iThreshold = filter->threshold; + iEdgeDetect = filter->edge_detect; + width = filter->width; + height = filter->height; + src = filter->src; + yuvptr = GST_BUFFER_DATA (buf); + bShowDeinterlacedAreaOnly = filter->show_deinterlaced_area_only; + + memcpy (filter->src, yuvptr, filter->picsize); + + y_dst = yuvptr; /* dst y pointer */ + /* we should not change u,v because one u, v value stands for */ + /* 2 pixels per 2 lines = 4 pixel and we don't want to change */ + /* the color of */ + + y_line = GST_VIDEO_I420_Y_ROWSTRIDE (width); + y_src = src; + + iThreshold = iThreshold * iThreshold * 4; + /* We don't want an integer overflow in the interlace calculation. */ + if (iEdgeDetect > 180) + iEdgeDetect = 180; + iEdgeDetect = iEdgeDetect * iEdgeDetect; + + y1 = 0; /* Avoid compiler warning. The value is not used. */ + for (x = 0; x < width; x++) { + psrc3 = y_src + x; + y3 = *psrc3; + psrc2 = psrc3 + y_line; + y2 = *psrc2; + pdst1 = y_dst + x; + iInterlaceValue1 = iInterlaceValue2 = 0; + for (y = 0; y <= height; y++) { + psrc1 = psrc2; + psrc2 = psrc3; + psrc3 = psrc3 + y_line; + y0 = y1; + y1 = y2; + y2 = y3; + if (y < height - 1) { + y3 = *psrc3; + } else { + y3 = y1; + } + + iInterlaceValue0 = iInterlaceValue1; + iInterlaceValue1 = iInterlaceValue2; + + if (y < height) + iInterlaceValue2 = ((y1 - y2) * (y3 - y2) - + ((iEdgeDetect * (y1 - y3) * (y1 - y3)) >> 12)) * 10; + else + iInterlaceValue2 = 0; + + if (y > 0) { + if (iInterlaceValue0 + 2 * iInterlaceValue1 + iInterlaceValue2 > + iThreshold) { + if (bBlend) { + *pdst1 = (unsigned char) ((y0 + 2 * y1 + y2) >> 2); + } else { + /* this method seems to work better than blending if the */ + /* quality is pretty bad and the half pics don't fit together */ + if ((y % 2) == 1) { /* if odd simply copy the value */ + *pdst1 = *psrc1; + /**pdst1 = 0; // FIXME this is for adjusting an initial iThreshold */ + } else { /* even interpolate the even line (upper + lower)/2 */ + *pdst1 = (unsigned char) ((y0 + y2) >> 1); + /**pdst1 = 0; // FIXME this is for adjusting an initial iThreshold */ + } + } + } else { + /* so we went below the treshold and therefore we don't have to */ + /* change anything */ + if (bShowDeinterlacedAreaOnly) { + /* this is for testing to see how we should tune the treshhold */ + /* and shows as the things that haven't change because the */ + /* threshhold was to low?? (or shows that everything is ok :-) */ + *pdst1 = 0; /* blank the point and so the interlac area */ + } else { + *pdst1 = *psrc1; + } + } + pdst1 = pdst1 + y_line; + } + } + } + + return GST_FLOW_OK; +} + +static void +th_deinterlace_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + ThDeinterlace *filter; + + filter = TH_DEINTERLACE (object); + + GST_OBJECT_LOCK (filter); + switch (prop_id) { + case ARG_DI_ONLY: + filter->show_deinterlaced_area_only = g_value_get_boolean (value); + break; + case ARG_BLEND: + filter->blend = g_value_get_boolean (value); + break; + case ARG_THRESHOLD: + filter->threshold = g_value_get_int (value); + break; + case ARG_EDGE_DETECT: + filter->edge_detect = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (filter); +} + +static void +th_deinterlace_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + ThDeinterlace *filter; + + filter = TH_DEINTERLACE (object); + + GST_OBJECT_LOCK (filter); + switch (prop_id) { + case ARG_DI_ONLY: + g_value_set_boolean (value, filter->show_deinterlaced_area_only); + break; + case ARG_BLEND: + g_value_set_boolean (value, filter->blend); + break; + case ARG_THRESHOLD: + g_value_set_int (value, filter->threshold); + break; + case ARG_EDGE_DETECT: + g_value_set_int (value, filter->edge_detect); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (filter); +} Added: trunk/thoggen/src/gst-plugins/th-deinterlace.h =================================================================== --- trunk/thoggen/src/gst-plugins/th-deinterlace.h (rev 0) +++ trunk/thoggen/src/gst-plugins/th-deinterlace.h 2006-08-23 23:21:13 UTC (rev 229) @@ -0,0 +1,65 @@ +/* Thoggen deinterlace plugin + * Copyright (C) 1999 Erik Walthinsen <om...@cs...> + * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net> + * + * (GStreamer-0.10 port of the GStreamer-0.8 deinterlace plugin) + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __TH_DEINTERLACE_H__ +#define __TH_DEINTERLACE_H__ + +#include <gst/gst.h> +#include <gst/base/gstbasetransform.h> + +G_BEGIN_DECLS + +#define TH_TYPE_DEINTERLACE (th_deinterlace_get_type()) +#define TH_DEINTERLACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),TH_TYPE_DEINTERLACE,ThDeinterlace)) +#define TH_DEINTERLACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),TH_TYPE_DEINTERLACE,ThDeinterlaceClass)) +#define TH_IS_DEINTERLACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),TH_TYPE_DEINTERLACE)) +#define TH_IS_DEINTERLACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),TH_TYPE_DEINTERLACE)) + +typedef struct _ThDeinterlace ThDeinterlace; +typedef struct _ThDeinterlaceClass ThDeinterlaceClass; + +struct _ThDeinterlace { + GstBaseTransform basetransform; + + gint width; + gint height; + + gboolean show_deinterlaced_area_only; + gboolean blend; + gint threshold_blend; /* here we start blending */ + gint threshold; /* here we start interpolating TODO FIXME */ + gint edge_detect; + + gint picsize; + guchar *src; +}; + +struct _ThDeinterlaceClass { + GstBaseTransformClass basetransformclass; +}; + +GType th_deinterlace_get_type (void); + +G_END_DECLS + +#endif /* __TH_DEINTERLACE_H__ */ + Modified: trunk/thoggen/src/gst-plugins/th-plugins.c =================================================================== --- trunk/thoggen/src/gst-plugins/th-plugins.c 2006-07-19 17:22:18 UTC (rev 228) +++ trunk/thoggen/src/gst-plugins/th-plugins.c 2006-08-23 23:21:13 UTC (rev 229) @@ -21,6 +21,7 @@ #include "th-plugins.h" #include "th-pixbufsink.h" +#include "th-deinterlace.h" /*************************************************************************** * @@ -56,6 +57,11 @@ return FALSE; } + if (!gst_element_register (plugin, "thdeinterlace", GST_RANK_NONE, + TH_TYPE_DEINTERLACE)) { + return FALSE; + } + return TRUE; } Modified: trunk/thoggen/src/th-job.c =================================================================== --- trunk/thoggen/src/th-job.c 2006-07-19 17:22:18 UTC (rev 228) +++ trunk/thoggen/src/th-job.c 2006-08-23 23:21:13 UTC (rev 229) @@ -1855,7 +1855,7 @@ " ! videorate " " ! video/x-raw-yuv,framerate=(fraction)%u/1 " " ! videobox left=%u right=%u top=%u bottom=%u " -/* " ! deinterlace " */ /* FIXME */ + " ! thdeinterlace " " ! videoscale method=bilinear " " ! video/x-raw-yuv,width=%u,height=%u " " ! theoraenc name=v-encoder " This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |