Commit b8931973 authored by Wim Taymans's avatar Wim Taymans
Browse files

media: port to 1.0

parent f94572fb
......@@ -326,6 +326,7 @@ AG_GST_CHECK_PLUGIN(isomp4)
AG_GST_CHECK_PLUGIN(law)
AG_GST_CHECK_PLUGIN(level)
AG_GST_CHECK_PLUGIN(matroska)
AG_GST_CHECK_PLUGIN(median)
AG_GST_CHECK_PLUGIN(monoscope)
AG_GST_CHECK_PLUGIN(multifile)
AG_GST_CHECK_PLUGIN(multipart)
......@@ -1082,6 +1083,7 @@ gst/isomp4/Makefile
gst/law/Makefile
gst/level/Makefile
gst/matroska/Makefile
gst/median/Makefile
gst/monoscope/Makefile
gst/multifile/Makefile
gst/multipart/Makefile
......
plugin_LTLIBRARIES = libgstmedian.la
libgstmedian_la_SOURCES = gstmedian.c
libgstmedian_la_CFLAGS = $(GST_CFLAGS)
libgstmedian_la_LIBADD = $(GST_LIBS)
libgstmedian_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) $(GST_CFLAGS)
libgstmedian_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_API_VERSION) \
$(GST_BASE_LIBS) $(GST_LIBS) $(LIBM)
libgstmedian_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstmedian_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstmedian.h
Android.mk: Makefile.am $(BUILT_SOURCES)
androgenizer \
-:PROJECT libgstmedian -:SHARED libgstmedian \
-:TAGS eng debug \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(libgstmedian_la_SOURCES) \
-:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstmedian_la_CFLAGS) \
-:LDFLAGS $(libgstmedian_la_LDFLAGS) \
$(libgstmedian_la_LIBADD) \
-ldl \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-1.0' \
> $@
......@@ -27,14 +27,14 @@
static GstStaticPadTemplate median_src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420"))
);
static GstStaticPadTemplate median_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("I420"))
);
......@@ -47,135 +47,71 @@ enum
enum
{
ARG_0,
ARG_ACTIVE,
ARG_FILTERSIZE,
ARG_LUM_ONLY
PROP_0,
PROP_ACTIVE,
PROP_FILTERSIZE,
PROP_LUM_ONLY
};
static GType gst_median_get_type (void);
static void gst_median_class_init (GstMedianClass * klass);
static void gst_median_base_init (GstMedianClass * klass);
static void gst_median_init (GstMedian * median);
#define gst_median_parent_class parent_class
G_DEFINE_TYPE (GstMedian, gst_median, GST_TYPE_VIDEO_FILTER);
static void median_5 (unsigned char *src, unsigned char *dest, int height,
int width);
static void median_5 (guint8 * src, gint sstride, const guint8 * dest,
gint dstride, gint width, gint height);
#if 0
static void median_9 (unsigned char *src, unsigned char *dest, int height,
int width);
static void gst_median_chain (GstPad * pad, GstData * _data);
#endif
static GstFlowReturn gst_median_transform_frame (GstVideoFilter * filter,
GstVideoFrame * in_frame, GstVideoFrame * out_frame);
static void gst_median_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_median_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstElementClass *parent_class = NULL;
/*static guint gst_median_signals[LAST_SIGNAL] = { 0 }; */
GType
gst_median_get_type (void)
{
static GType median_type = 0;
if (!median_type) {
static const GTypeInfo median_info = {
sizeof (GstMedianClass),
(GBaseInitFunc) gst_median_base_init,
NULL,
(GClassInitFunc) gst_median_class_init,
NULL,
NULL,
sizeof (GstMedian),
0,
(GInstanceInitFunc) gst_median_init,
};
median_type =
g_type_register_static (GST_TYPE_ELEMENT, "GstMedian", &median_info, 0);
}
return median_type;
}
static void
gst_median_base_init (GstMedianClass * klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&median_sink_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&median_src_factory));
gst_element_class_set_static_metadata (element_class, "Median effect",
"Filter/Effect/Video",
"Apply a median filter to an image",
"Wim Taymans <wim.taymans@chello.be>");
}
static void
gst_median_class_init (GstMedianClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstVideoFilterClass *vfilter_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
vfilter_class = (GstVideoFilterClass *) klass;
parent_class = g_type_class_peek_parent (klass);
gobject_class->set_property = gst_median_set_property;
gobject_class->get_property = gst_median_get_property;
/* FIXME: add long property descriptions */
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ACTIVE,
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ACTIVE,
g_param_spec_boolean ("active", "active", "active", TRUE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FILTERSIZE,
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILTERSIZE,
g_param_spec_int ("filtersize", "filtersize", "filtersize", G_MININT,
G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LUM_ONLY,
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LUM_ONLY,
g_param_spec_boolean ("lum-only", "lum-only", "lum-only", TRUE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gobject_class->set_property = gst_median_set_property;
gobject_class->get_property = gst_median_get_property;
}
static gboolean
gst_median_link (GstPad * pad, const GstCaps * caps)
{
GstMedian *filter = GST_MEDIAN (gst_pad_get_parent (pad));
GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
GstStructure *structure = gst_caps_get_structure (caps, 0);
gint w, h;
GstPadLinkReturn ret;
gst_structure_get_int (structure, "width", &w);
gst_structure_get_int (structure, "height", &h);
ret = gst_pad_try_set_caps (otherpad, caps);
if (GST_PAD_LINK_SUCCESSFUL (ret)) {
filter->width = w;
filter->height = h;
}
gst_object_unref (filter);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&median_sink_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&median_src_factory));
gst_element_class_set_static_metadata (gstelement_class, "Median effect",
"Filter/Effect/Video",
"Apply a median filter to an image",
"Wim Taymans <wim.taymans@gmail.com>");
return ret;
vfilter_class->transform_frame =
GST_DEBUG_FUNCPTR (gst_median_transform_frame);
}
void
gst_median_init (GstMedian * median)
{
median->sinkpad =
gst_pad_new_from_static_template (&media_sink_factory, "sink");
gst_pad_set_getcaps_function (median->sinkpad, gst_pad_proxy_getcaps);
gst_pad_set_link_function (median->sinkpad, gst_median_link);
gst_pad_set_chain_function (median->sinkpad, gst_median_chain);
gst_element_add_pad (GST_ELEMENT (median), median->sinkpad);
median->srcpad = gst_pad_new_from_static_template (&media_src_factory, "src");
gst_pad_set_getcaps_function (median->srcpad, gst_pad_proxy_getcaps);
gst_pad_set_link_function (median->sinkpad, gst_median_link);
gst_element_add_pad (GST_ELEMENT (median), median->srcpad);
median->filtersize = 5;
median->lum_only = TRUE;
median->active = TRUE;
......@@ -185,35 +121,30 @@ gst_median_init (GstMedian * median)
#define PIX_SWAP(a,b) { unsigned char temp=(a);(a)=(b);(b)=temp; }
static void
median_5 (unsigned char *src, unsigned char *dest, int width, int height)
median_5 (guint8 * dest, gint dstride, const guint8 * src, gint sstride,
gint width, gint height)
{
int nLastRow;
int nLastCol;
unsigned char p[9];
unsigned char p[5];
int i, j, k;
nLastCol = width - 1;
nLastRow = height - 1;
/*copy the top and bottom rows into the result array */
/* copy the top and bottom rows into the result array */
for (i = 0; i < width; i++) {
dest[i] = src[i];
dest[nLastRow * width + i] = src[nLastRow * width + i];
dest[(height - 1) * dstride + i] = src[(height - 1) * sstride + i];
}
dest[i] = src[i];
nLastCol--;
nLastRow--;
/* process the interior pixels */
i = width + 1;
for (k = 0; k < nLastRow; k++) {
for (j = 0; j < nLastCol; j++, i++) {
p[0] = src[i - width];
for (k = 2; k < height; k++) {
dest += dstride;
src += sstride;
dest[0] = src[0];
for (j = 2, i = 1; j < width; j++, i++) {
p[0] = src[i - sstride];
p[1] = src[i - 1];
p[2] = src[i];
p[3] = src[i + 1];
p[4] = src[i + width];
p[4] = src[i + sstride];
PIX_SORT (p[0], p[1]);
PIX_SORT (p[3], p[4]);
PIX_SORT (p[0], p[3]);
......@@ -224,48 +155,37 @@ median_5 (unsigned char *src, unsigned char *dest, int width, int height)
dest[i] = p[2];
}
dest[i] = src[i];
i++;
dest[i] = src[i];
i++;
}
dest[i] = src[i];
i++;
}
static void
median_9 (unsigned char *src, unsigned char *dest, int width, int height)
median_9 (guint8 * dest, gint dstride, const guint8 * src, gint sstride,
gint width, gint height)
{
int nLastRow;
int nLastCol;
unsigned char p[9];
int i, j, k;
nLastCol = width - 1;
nLastRow = height - 1;
/*copy the top and bottom rows into the result array */
for (i = 0; i < width; i++) {
dest[i] = src[i];
dest[nLastRow * width + i] = src[nLastRow * width + i];
dest[(height - 1) * dstride + i] = src[(height - 1) * sstride + i];
}
dest[i] = src[i];
nLastCol--;
nLastRow--;
/* process the interior pixels */
i = width + 1;
for (k = 0; k < nLastRow; k++) {
for (j = 0; j < nLastCol; j++, i++) {
p[0] = src[i - width - 1];
p[1] = src[i - width];
p[2] = src[i - width + 1];
for (k = 2; k < height; k++) {
dest += dstride;
src += sstride;
dest[0] = src[0];
for (j = 2, i = 1; j < width; j++, i++) {
p[0] = src[i - sstride - 1];
p[1] = src[i - sstride];
p[2] = src[i - sstride + 1];
p[3] = src[i - 1];
p[4] = src[i];
p[5] = src[i + 1];
p[6] = src[i + width - 1];
p[7] = src[i + width];
p[8] = src[i + width + 1];
p[6] = src[i + sstride - 1];
p[7] = src[i + sstride];
p[8] = src[i + sstride + 1];
PIX_SORT (p[1], p[2]);
PIX_SORT (p[4], p[5]);
PIX_SORT (p[7], p[8]);
......@@ -288,79 +208,66 @@ median_9 (unsigned char *src, unsigned char *dest, int width, int height)
dest[i] = p[4];
}
dest[i] = src[i];
i++;
dest[i] = src[i];
i++;
}
dest[i] = src[i];
i++;
}
static void
gst_median_chain (GstPad * pad, GstData * _data)
static GstFlowReturn
gst_median_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame,
GstVideoFrame * out_frame)
{
GstBuffer *buf = GST_BUFFER (_data);
GstMedian *median;
guchar *data;
gulong size;
GstBuffer *outbuf;
/* GstMeta *meta; */
int lumsize, chromsize;
g_return_if_fail (pad != NULL);
g_return_if_fail (GST_IS_PAD (pad));
g_return_if_fail (buf != NULL);
median = GST_MEDIAN (GST_OBJECT_PARENT (pad));
if (!median->active) {
gst_pad_push (median->srcpad, GST_DATA (buf));
return;
}
data = GST_BUFFER_DATA (buf);
size = GST_BUFFER_SIZE (buf);
GST_DEBUG ("median: have buffer of %d", GST_BUFFER_SIZE (buf));
outbuf = gst_buffer_new ();
GST_BUFFER_DATA (outbuf) = g_malloc (GST_BUFFER_SIZE (buf));
GST_BUFFER_SIZE (outbuf) = GST_BUFFER_SIZE (buf);
lumsize = median->width * median->height;
chromsize = lumsize / 4;
GstMedian *median = GST_MEDIAN (filter);
if (median->filtersize == 5) {
median_5 (data, GST_BUFFER_DATA (outbuf), median->width, median->height);
if (!median->lum_only) {
median_5 (data + lumsize, GST_BUFFER_DATA (outbuf) + lumsize,
median->width / 2, median->height / 2);
median_5 (data + lumsize + chromsize,
GST_BUFFER_DATA (outbuf) + lumsize + chromsize, median->width / 2,
median->height / 2);
median_5 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0),
GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0),
GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0),
GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0),
GST_VIDEO_FRAME_WIDTH (in_frame), GST_VIDEO_FRAME_HEIGHT (in_frame));
if (median->lum_only) {
gst_video_frame_copy_plane (out_frame, in_frame, 1);
gst_video_frame_copy_plane (out_frame, in_frame, 2);
} else {
memcpy (GST_BUFFER_DATA (outbuf) + lumsize, data + lumsize,
chromsize * 2);
median_5 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 1),
GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 1),
GST_VIDEO_FRAME_PLANE_DATA (in_frame, 1),
GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 1),
GST_VIDEO_FRAME_WIDTH (in_frame) / 2,
GST_VIDEO_FRAME_HEIGHT (in_frame) / 2);
median_5 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 2),
GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 2),
GST_VIDEO_FRAME_PLANE_DATA (in_frame, 2),
GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 2),
GST_VIDEO_FRAME_WIDTH (in_frame) / 2,
GST_VIDEO_FRAME_HEIGHT (in_frame) / 2);
}
} else {
median_9 (data, GST_BUFFER_DATA (outbuf), median->width, median->height);
if (!median->lum_only) {
median_9 (data + lumsize, GST_BUFFER_DATA (outbuf) + lumsize,
median->width / 2, median->height / 2);
median_9 (data + lumsize + chromsize,
GST_BUFFER_DATA (outbuf) + lumsize + chromsize, median->width / 2,
median->height / 2);
median_9 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 0),
GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 0),
GST_VIDEO_FRAME_PLANE_DATA (in_frame, 0),
GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 0),
GST_VIDEO_FRAME_WIDTH (in_frame), GST_VIDEO_FRAME_HEIGHT (in_frame));
if (median->lum_only) {
gst_video_frame_copy_plane (out_frame, in_frame, 1);
gst_video_frame_copy_plane (out_frame, in_frame, 2);
} else {
memcpy (GST_BUFFER_DATA (outbuf) + lumsize, data + lumsize,
chromsize * 2);
median_9 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 1),
GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 1),
GST_VIDEO_FRAME_PLANE_DATA (in_frame, 1),
GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 1),
GST_VIDEO_FRAME_WIDTH (in_frame) / 2,
GST_VIDEO_FRAME_HEIGHT (in_frame) / 2);
median_9 (GST_VIDEO_FRAME_PLANE_DATA (out_frame, 2),
GST_VIDEO_FRAME_PLANE_STRIDE (out_frame, 2),
GST_VIDEO_FRAME_PLANE_DATA (in_frame, 2),
GST_VIDEO_FRAME_PLANE_STRIDE (in_frame, 2),
GST_VIDEO_FRAME_WIDTH (in_frame) / 2,
GST_VIDEO_FRAME_HEIGHT (in_frame) / 2);
}
}
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
gst_buffer_unref (buf);
gst_pad_push (median->srcpad, GST_DATA (outbuf));
return GST_FLOW_OK;
}
static void
......@@ -374,7 +281,7 @@ gst_median_set_property (GObject * object, guint prop_id, const GValue * value,
median = GST_MEDIAN (object);
switch (prop_id) {
case ARG_FILTERSIZE:
case PROP_FILTERSIZE:
argvalue = g_value_get_int (value);
if (argvalue != 5 && argvalue != 9) {
g_warning ("median: invalid filtersize (%d), must be 5 or 9\n",
......@@ -383,10 +290,10 @@ gst_median_set_property (GObject * object, guint prop_id, const GValue * value,
median->filtersize = argvalue;
}
break;
case ARG_ACTIVE:
case PROP_ACTIVE:
median->active = g_value_get_boolean (value);
break;
case ARG_LUM_ONLY:
case PROP_LUM_ONLY:
median->lum_only = g_value_get_boolean (value);
break;
default:
......@@ -404,13 +311,13 @@ gst_median_get_property (GObject * object, guint prop_id, GValue * value,
median = GST_MEDIAN (object);
switch (prop_id) {
case ARG_FILTERSIZE:
case PROP_FILTERSIZE:
g_value_set_int (value, median->filtersize);
break;
case ARG_ACTIVE:
case PROP_ACTIVE:
g_value_set_boolean (value, median->active);
break;
case ARG_LUM_ONLY:
case PROP_LUM_ONLY:
g_value_set_boolean (value, median->lum_only);
break;
default:
......
......@@ -23,12 +23,10 @@
#include <gst/gst.h>
#include <gst/video/video.h>
#include <gst/video/gstvideofilter.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
G_BEGIN_DECLS
#define GST_TYPE_MEDIAN \
(gst_median_get_type())
......@@ -45,7 +43,7 @@ typedef struct _GstMedian GstMedian;
typedef struct _GstMedianClass GstMedianClass;
struct _GstMedian {
GstElement element;
GstVideoFilter parent;
int format;
int width;
......@@ -60,12 +58,11 @@ struct _GstMedian {
};
struct _GstMedianClass {
GstElementClass parent_class;
GstVideoFilterClass parent_class;
};
#ifdef __cplusplus
}
#endif /* __cplusplus */
GType gst_median_get_type (void);
G_END_DECLS
#endif /* __GST_MEDIAN_H__ */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment