Skip to content
Snippets Groups Projects
Commit 65804f62 authored by Matthias Rabe's avatar Matthias Rabe
Browse files

gst: add pseudocolor2 plugin

parent 043e32b3
Branches jethro
Tags
No related merge requests found
From 35ca4da4f9ed3fe4c32cf83ecd4fa2e11fb86058 Mon Sep 17 00:00:00 2001
From: Matthias Rabe <matthias.rabe@sigma-chemnitz.de>
Date: Thu, 3 Nov 2016 10:07:48 +0100
Subject: [PATCH] videofilters: add plugin pseudocolor2
Signed-off-by: Matthias Rabe <matthias.rabe@sigma-chemnitz.de>
---
gst/videofilters/Makefile.am | 2 +
gst/videofilters/gstpseudocolor2.c | 410 ++++++++++++++++++++++++++++++++++
gst/videofilters/gstpseudocolor2.h | 68 ++++++
gst/videofilters/gstvideofiltersbad.c | 3 +
4 files changed, 483 insertions(+)
create mode 100644 gst/videofilters/gstpseudocolor2.c
create mode 100644 gst/videofilters/gstpseudocolor2.h
diff --git a/gst/videofilters/Makefile.am b/gst/videofilters/Makefile.am
index 4498d4a..920dbe4 100644
--- a/gst/videofilters/Makefile.am
+++ b/gst/videofilters/Makefile.am
@@ -11,6 +11,8 @@ libgstvideofiltersbad_la_SOURCES = \
gstvideodiff.h \
gstpseudocolor.c \
gstpseudocolor.h \
+ gstpseudocolor2.c \
+ gstpseudocolor2.h \
gstvideofiltersbad.c
#nodist_libgstvideofiltersbad_la_SOURCES = $(ORC_NODIST_SOURCES)
libgstvideofiltersbad_la_CFLAGS = \
diff --git a/gst/videofilters/gstpseudocolor2.c b/gst/videofilters/gstpseudocolor2.c
new file mode 100644
index 0000000..b2aa3b2
--- /dev/null
+++ b/gst/videofilters/gstpseudocolor2.c
@@ -0,0 +1,410 @@
+/* GStreamer
+ * Author: Matthias Rabe <matthias.rabe@sigma-chemnitz.de>
+ *
+ * based on pseudocode by
+ * Author: Ravi Kiran K N <ravi.kiran@samsung.com>
+ *
+ * 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 Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+/**
+ * SECTION:element-gstpseudocolor2
+ *
+ * The pseudocolor2 element applies pseudo-color effect on gray scale image
+ * but requires a lookup table
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v videotestsrc ! pseudocolor location=<fname> invert=<0/1> ! videoconvert ! autovideosink
+ * ]|
+ *
+ * invert = invert graycolor
+ *
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/video/video.h>
+#include <gst/video/gstvideofilter.h>
+#include "gstpseudocolor2.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#define DEFAULT_INVERT 1
+
+GST_DEBUG_CATEGORY_STATIC (gst_pseudo_color2_debug_category);
+#define GST_CAT_DEFAULT gst_pseudo_color2_debug_category
+
+
+static gboolean
+gst_pseudo_color2_set_info (GstVideoFilter * vfilter, GstCaps * in,
+ GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info);
+
+static GstFlowReturn gst_pseudo_color2_transform_frame (GstVideoFilter * filter,
+ GstVideoFrame * inframe, GstVideoFrame * outframe);
+
+static void gst_pseudo_color2_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+
+static void gst_pseudo_color2_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+
+static void gst_pseudo_color2_process_rgb (GstPseudoColor2 * pcolor,
+ GstVideoFrame * src_frame, GstVideoFrame * dest_frame);
+
+
+enum
+{
+ PROP_0,
+ PROP_LOCACTION,
+ PROP_INVERT,
+};
+
+/* pad templates */
+
+#define VIDEO_SRC_CAPS \
+ GST_VIDEO_CAPS_MAKE("{ RGB }")
+
+#define VIDEO_SINK_CAPS \
+ GST_VIDEO_CAPS_MAKE("{ GRAY8 }")
+
+
+/* class initialization */
+#define gst_pseudo_color2_parent_class parent_class
+G_DEFINE_TYPE_WITH_CODE (GstPseudoColor2, gst_pseudo_color2,
+ GST_TYPE_VIDEO_FILTER,
+ GST_DEBUG_CATEGORY_INIT (gst_pseudo_color2_debug_category, "pseudocolor2",
+ 0, "debug category for pseudocolor2 element"));
+
+
+static void
+gst_pseudo_color2_finalize (GObject * object)
+{
+ GstPseudoColor2 *pcolor = GST_PSEUDO_COLOR2 (object);
+
+ g_mutex_clear (&pcolor->mutex);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_pseudo_color2_set_info (GstVideoFilter * vfilter, GstCaps * in,
+ GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info)
+{
+ GstPseudoColor2 *pcolor = GST_PSEUDO_COLOR2 (vfilter);
+
+ g_mutex_lock (&pcolor->mutex);
+
+ switch (GST_VIDEO_INFO_FORMAT (out_info)) {
+ case GST_VIDEO_FORMAT_RGB:
+ pcolor->process = gst_pseudo_color2_process_rgb;
+ break;
+ default:
+ pcolor->process = NULL;
+ break;
+ }
+
+ g_mutex_unlock (&pcolor->mutex);
+
+ return pcolor->process != NULL;
+}
+
+static gboolean
+gst_pseudo_color2_check_input_format (const GValue * val, gboolean * is_gray,
+ gboolean * is_rgb)
+{
+ const gchar *str;
+ if ((str = g_value_get_string (val))) {
+ if (strcmp (str, "GRAY8") == 0) {
+ *is_gray = TRUE;
+ } else if (strcmp (str, "RGB") == 0) {
+ *is_rgb = TRUE;
+ }
+ }
+ return (*is_gray || *is_rgb);
+}
+
+static GstCaps *
+gst_pseudo_color2_transform_caps (GstBaseTransform * trans,
+ GstPadDirection direction, GstCaps * from, GstCaps * filter)
+{
+ GstPseudoColor2 *pcolor = GST_PSEUDO_COLOR2 (trans);
+
+ GstCaps *to, *ret;
+ GstCaps *templ;
+ GstStructure *structure;
+ GstPad *other;
+ gint i, j;
+
+ to = gst_caps_new_empty ();
+ for (i = 0; i < gst_caps_get_size (from); i++) {
+ const GValue *fval, *lval;
+ GValue list = { 0, };
+ GValue val = { 0, };
+ gboolean is_gray = FALSE, is_rgb = FALSE;
+
+ structure = gst_structure_copy (gst_caps_get_structure (from, i));
+
+ /* Supported conversions:
+ * GRAY8->RGB
+ */
+ fval = gst_structure_get_value (structure, "format");
+ if (fval && GST_VALUE_HOLDS_LIST (fval)) {
+ for (j = 0; j < gst_value_list_get_size (fval); j++) {
+ lval = gst_value_list_get_value (fval, j);
+ if (gst_pseudo_color2_check_input_format (lval, &is_gray, &is_rgb))
+ break;
+ }
+ } else if (fval && G_VALUE_HOLDS_STRING (fval)) {
+ gst_pseudo_color2_check_input_format (fval, &is_gray, &is_rgb);
+ }
+
+ if (is_gray || is_rgb) {
+ g_value_init (&list, GST_TYPE_LIST);
+ g_value_init (&val, G_TYPE_STRING);
+
+ if (is_gray) {
+ g_value_set_string (&val, "RGB");
+ gst_value_list_append_value (&list, &val);
+ g_value_unset (&val);
+ }
+ if (is_rgb) {
+ g_value_set_string (&val, "GRAY8");
+ gst_value_list_append_value (&list, &val);
+ g_value_unset (&val);
+ }
+
+ gst_value_list_merge (&val, fval, &list);
+ gst_structure_set_value (structure, "format", &val);
+ g_value_unset (&val);
+ g_value_unset (&list);
+
+ }
+
+ gst_caps_append_structure (to, structure);
+ }
+
+ /* filter the 'to' caps (transform caps) against allowed caps on the pad */
+ other = (direction == GST_PAD_SINK) ? trans->srcpad : trans->sinkpad;
+ templ = gst_pad_get_pad_template_caps (other);
+
+ ret = gst_caps_intersect (to, templ);
+
+ gst_caps_unref (to);
+ gst_caps_unref (templ);
+
+ GST_DEBUG_OBJECT (pcolor, "direction %d, transformed %" GST_PTR_FORMAT
+ " to %" GST_PTR_FORMAT, direction, from, ret);
+
+
+ if (ret && filter) {
+ GstCaps *intersection;
+
+ GST_DEBUG_OBJECT (pcolor, "Using filter caps %" GST_PTR_FORMAT,
+ filter);
+ intersection =
+ gst_caps_intersect_full (filter, ret, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (ret);
+ ret = intersection;
+ GST_DEBUG_OBJECT (pcolor, "Intersection %" GST_PTR_FORMAT, ret);
+ }
+
+ return ret;
+}
+
+static void
+gst_pseudo_color2_class_init (GstPseudoColor2Class * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass);
+ GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
+
+
+ gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
+ gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
+ gst_caps_from_string (VIDEO_SRC_CAPS)));
+ gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
+ gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
+ gst_caps_from_string (VIDEO_SINK_CAPS)));
+
+ video_filter_class->transform_frame =
+ GST_DEBUG_FUNCPTR (gst_pseudo_color2_transform_frame);
+ video_filter_class->set_info = GST_DEBUG_FUNCPTR (gst_pseudo_color2_set_info);
+
+ trans_class->transform_caps =
+ GST_DEBUG_FUNCPTR (gst_pseudo_color2_transform_caps);
+
+ gobject_class->set_property = gst_pseudo_color2_set_property;
+ gobject_class->get_property = gst_pseudo_color2_get_property;
+ gobject_class->finalize = gst_pseudo_color2_finalize;
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LOCACTION,
+ g_param_spec_string ("location", "Location",
+ "Location of pseudocolor look up table",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+
+ g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_INVERT,
+ g_param_spec_uint ("invert", "invert",
+ "invert graycolor (default: 1)", 0, 1,
+ DEFAULT_INVERT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
+
+ gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
+ "pseudocolor2", "Transform/Effect/Video",
+ "apply pseudo-color to grayscale image",
+ "Matthias Rabe <matthias.rabe@sigma-chemnitz.de>");
+}
+
+static void
+gst_pseudo_color2_set_location (GstPseudoColor2 * pcolor, const gchar * location)
+{
+ FILE *f = NULL;
+ unsigned i = 0;
+
+ GST_DEBUG_OBJECT (pcolor, "Setting location to %s", location);
+ g_free (pcolor->location);
+ pcolor->location = g_strdup (location);
+
+ GST_DEBUG_OBJECT (pcolor, "Read pseudo color tbl");
+ if (!(f = fopen (pcolor->location, "r"))) {
+ GST_ERROR_OBJECT (pcolor, "failed to open file for reading");
+ }
+ for (i = 0; i < PSEUDO_TBL_SIZE; i++) {
+ pcolor->pseudo_tbl[i].rgb[0] = getc (f);
+ pcolor->pseudo_tbl[i].rgb[1] = getc (f);
+ pcolor->pseudo_tbl[i].rgb[2] = getc (f);
+ }
+ fclose (f);
+}
+
+static void
+gst_pseudo_color2_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstPseudoColor2 *pcolor = GST_PSEUDO_COLOR2 (object);
+
+ g_mutex_lock (&pcolor->mutex);
+ switch (prop_id) {
+ case PROP_LOCACTION:
+ gst_pseudo_color2_set_location (pcolor, g_value_get_string (value));
+ break;
+ case PROP_INVERT:
+ pcolor->invert = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ g_mutex_unlock (&pcolor->mutex);
+}
+
+static void
+gst_pseudo_color2_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstPseudoColor2 *pcolor = GST_PSEUDO_COLOR2 (object);
+
+ switch (prop_id) {
+ case PROP_LOCACTION:
+ g_value_set_string (value, pcolor->location);
+ break;
+ case PROP_INVERT:
+ g_value_set_uint (value, pcolor->invert);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_pseudo_color2_init (GstPseudoColor2 * pcolor)
+{
+ unsigned long i = 0, j = 0;
+
+ pcolor->invert = DEFAULT_INVERT;
+ pcolor->location = NULL;
+ pcolor->process = NULL;
+
+ for (i = 0; i < PSEUDO_TBL_SIZE; i++) {
+ for (j = 0; j < 3; j++) {
+ pcolor->pseudo_tbl[i].rgb[j] = i; /* default */
+ }
+ }
+
+ g_mutex_init (&pcolor->mutex);
+}
+
+static void
+gst_pseudo_color2_process_rgb (GstPseudoColor2 * pcolor,
+ GstVideoFrame * src_frame, GstVideoFrame * dest_frame)
+{
+ gint i, j;
+ gint w, h;
+ guint8 *src, *dest;
+ gint dest_stride, src_stride, src_pixel_stride, dest_pixel_stride;
+
+ src = GST_VIDEO_FRAME_PLANE_DATA (src_frame, 0);
+ src_stride = GST_VIDEO_FRAME_PLANE_STRIDE (src_frame, 0);
+ src_pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (src_frame, 0);
+ dest = GST_VIDEO_FRAME_PLANE_DATA (dest_frame, 0);
+ dest_stride = GST_VIDEO_FRAME_PLANE_STRIDE (dest_frame, 0);
+ dest_pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (dest_frame, 0);
+ h = GST_VIDEO_FRAME_HEIGHT (src_frame);
+ w = GST_VIDEO_FRAME_WIDTH (src_frame);
+
+ for (i = 0; i < h; i++) {
+ for (j = 0; j < w; j++) {
+ guint graypix = (guint) src[j * src_pixel_stride];
+
+ if (graypix >= PSEUDO_TBL_SIZE) {
+ GST_ERROR_OBJECT (pcolor, "graypix(=%u) out of bound", graypix);
+ graypix = PSEUDO_TBL_SIZE - 1;
+ }
+
+ if (pcolor->invert)
+ graypix = 255 - graypix;
+
+ dest[j * dest_pixel_stride] = pcolor->pseudo_tbl[graypix].rgb[0];
+ dest[j * dest_pixel_stride + 1] = pcolor->pseudo_tbl[graypix].rgb[1];
+ dest[j * dest_pixel_stride + 2] = pcolor->pseudo_tbl[graypix].rgb[2];
+ }
+ dest += dest_stride;
+ src += src_stride;
+ }
+}
+
+static GstFlowReturn
+gst_pseudo_color2_transform_frame (GstVideoFilter * filter,
+ GstVideoFrame * src_frame, GstVideoFrame * dest_frame)
+{
+ GstPseudoColor2 *pcolor = GST_PSEUDO_COLOR2 (filter);
+
+ g_mutex_lock (&pcolor->mutex);
+
+ if (pcolor->process)
+ pcolor->process (pcolor, src_frame, dest_frame);
+
+ g_mutex_unlock (&pcolor->mutex);
+
+ return GST_FLOW_OK;
+}
diff --git a/gst/videofilters/gstpseudocolor2.h b/gst/videofilters/gstpseudocolor2.h
new file mode 100644
index 0000000..409ae0d
--- /dev/null
+++ b/gst/videofilters/gstpseudocolor2.h
@@ -0,0 +1,68 @@
+/* GStreamer
+ * Copyright (C) 2015 Samsung Electronics. All rights reserved.
+ * Author: Ravi Kiran K N <ravi.kiran@samsung.com>
+ *
+ * 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 Street, Suite 500,
+ * Boston, MA 02110-1335, USA.
+ */
+
+#ifndef _GST_PSEUDO_COLOR2_H_
+#define _GST_PSEUDO_COLOR2_H_
+
+#include <gst/video/video.h>
+#include <gst/video/gstvideofilter.h>
+#include <string.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_PSEUDO_COLOR2 (gst_pseudo_color2_get_type())
+#define GST_PSEUDO_COLOR2(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PSEUDO_COLOR2,GstPseudoColor2))
+#define GST_PSEUDO_COLOR2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PSEUDO_COLOR2,GstPseudoColorClass))
+#define GST_IS_PSEUDO_COLOR2(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PSEUDO_COLOR2))
+#define GST_IS_PSEUDO_COLOR2_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PSEUDO_COLOR2))
+
+typedef struct _GstPseudoColor2 GstPseudoColor2;
+typedef struct _GstPseudoColor2Class GstPseudoColor2Class;
+
+#define PSEUDO_TBL_SIZE 256
+
+struct GstPseudoColorRGB
+{
+ gint rgb[3];
+};
+
+struct _GstPseudoColor2
+{
+ GstVideoFilter base_pseudocolor;
+
+ GMutex mutex;
+
+ gchar *location;
+ guint invert;
+ struct GstPseudoColorRGB pseudo_tbl[PSEUDO_TBL_SIZE];
+
+ void (*process)(GstPseudoColor2* filter, GstVideoFrame * src_frame, GstVideoFrame * dest_frame);
+};
+
+struct _GstPseudoColor2Class
+{
+ GstVideoFilterClass base_pseudocolor2_class;
+};
+
+GType gst_pseudo_color2_get_type (void);
+
+G_END_DECLS
+
+#endif /* _GST_PSEUDO_COLOR_H_ */
diff --git a/gst/videofilters/gstvideofiltersbad.c b/gst/videofilters/gstvideofiltersbad.c
index f7a00f9..7d2f8e0 100644
--- a/gst/videofilters/gstvideofiltersbad.c
+++ b/gst/videofilters/gstvideofiltersbad.c
@@ -27,6 +27,7 @@
#include "gstzebrastripe.h"
#include "gstvideodiff.h"
#include "gstpseudocolor.h"
+#include "gstpseudocolor2.h"
static gboolean
@@ -39,6 +40,8 @@ plugin_init (GstPlugin * plugin)
gst_zebra_stripe_get_type ());
gst_element_register (plugin, "pseudocolor", GST_RANK_NONE,
gst_pseudo_color_get_type ());
+ gst_element_register (plugin, "pseudocolor2", GST_RANK_NONE,
+ gst_pseudo_color2_get_type ());
return gst_element_register (plugin, "videodiff", GST_RANK_NONE,
GST_TYPE_VIDEO_DIFF);
--
2.5.5
File added
......@@ -2,4 +2,13 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/files:"
SRC_URI_append = " \
file://0001-videofilters-Add-plugin-for-pseudo-color-effect.patch \
file://0002-videofilters-add-plugin-pseudocolor2.patch \
file://pcolor_farbschema.rgb \
"
do_install_append () {
mkdir -p ${D}${datadir}/gst-plugins-bad/1.0/pcolor
install -m 644 ${WORKDIR}/pcolor_farbschema.rgb \
${D}${datadir}/gst-plugins-bad/1.0/pcolor/
}
FILES_${PN}-videofiltersbad += " ${datadir}/gst-plugins-bad/1.0/pcolor"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment