From 5c1eb82b8a43ff912b47410a6cfbec2c8d1e1078 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 3 Jun 2010 15:53:04 -0700 Subject: [PATCH] bayer: Add rgb2bayer element Mostly for testing/completeness. --- gst/bayer/Makefile.am | 6 +- gst/bayer/gstbayer.c | 4 +- gst/bayer/gstrgb2bayer.c | 353 +++++++++++++++++++++++++++++++++++++++ gst/bayer/gstrgb2bayer.h | 53 ++++++ 4 files changed, 414 insertions(+), 2 deletions(-) create mode 100644 gst/bayer/gstrgb2bayer.c create mode 100644 gst/bayer/gstrgb2bayer.h diff --git a/gst/bayer/Makefile.am b/gst/bayer/Makefile.am index 7b916633e0..8bcdb09f18 100644 --- a/gst/bayer/Makefile.am +++ b/gst/bayer/Makefile.am @@ -1,6 +1,10 @@ plugin_LTLIBRARIES = libgstbayer.la -libgstbayer_la_SOURCES = gstbayer.c gstbayer2rgb.c +libgstbayer_la_SOURCES = \ + gstbayer.c \ + gstbayer2rgb.c \ + gstrgb2bayer.c \ + gstrgb2bayer.h libgstbayer_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \ $(GST_CFLAGS) libgstbayer_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) \ diff --git a/gst/bayer/gstbayer.c b/gst/bayer/gstbayer.c index 1e944d13b0..a1ae9a734f 100644 --- a/gst/bayer/gstbayer.c +++ b/gst/bayer/gstbayer.c @@ -23,15 +23,17 @@ #include -#include GType gst_bayer2rgb_get_type (void); +GType gst_rgb2bayer_get_type (void); static gboolean plugin_init (GstPlugin * plugin) { gst_element_register (plugin, "bayer2rgb", GST_RANK_NONE, gst_bayer2rgb_get_type ()); + gst_element_register (plugin, "rgb2bayer", GST_RANK_NONE, + gst_rgb2bayer_get_type ()); return TRUE; } diff --git a/gst/bayer/gstrgb2bayer.c b/gst/bayer/gstrgb2bayer.c new file mode 100644 index 0000000000..b6de5f8b52 --- /dev/null +++ b/gst/bayer/gstrgb2bayer.c @@ -0,0 +1,353 @@ +/* GStreamer + * Copyright (C) 2010 David Schleef + * + * 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. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "gstrgb2bayer.h" + +#define GST_CAT_DEFAULT gst_rgb2bayer_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +/* prototypes */ + + +static void gst_rgb2bayer_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_rgb2bayer_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_rgb2bayer_dispose (GObject * object); +static void gst_rgb2bayer_finalize (GObject * object); + +static GstCaps *gst_rgb2bayer_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps); +static gboolean +gst_rgb2bayer_get_unit_size (GstBaseTransform * trans, GstCaps * caps, + guint * size); +static gboolean +gst_rgb2bayer_set_caps (GstBaseTransform * trans, GstCaps * incaps, + GstCaps * outcaps); +static gboolean gst_rgb2bayer_start (GstBaseTransform * trans); +static gboolean gst_rgb2bayer_stop (GstBaseTransform * trans); +static gboolean gst_rgb2bayer_event (GstBaseTransform * trans, + GstEvent * event); +static GstFlowReturn gst_rgb2bayer_transform (GstBaseTransform * trans, + GstBuffer * inbuf, GstBuffer * outbuf); +static gboolean gst_rgb2bayer_src_event (GstBaseTransform * trans, + GstEvent * event); + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate gst_rgb2bayer_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_ARGB) + ); + +#if 0 +/* do these later */ +static GstStaticPadTemplate gst_rgb2bayer_sink_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_xRGB ";" + GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_xBGR ";" + GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_ARGB ";" + GST_VIDEO_CAPS_BGRA ";" GST_VIDEO_CAPS_ABGR) + ); +#endif + +static GstStaticPadTemplate gst_rgb2bayer_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-bayer,width=[1,MAX],height=[1,MAX]," + "framerate=(fraction)[0/1,MAX]") + ); + +/* class initialization */ + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_rgb2bayer_debug, "rgb2bayer", 0, "rgb2bayer element"); + +GST_BOILERPLATE_FULL (GstRGB2Bayer, gst_rgb2bayer, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); + +static void +gst_rgb2bayer_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 (&gst_rgb2bayer_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rgb2bayer_sink_template)); + + gst_element_class_set_details_simple (element_class, + "RGB to Bayer converter", + "Filter/Converter/Video", + "Converts video/x-raw-rgb to video/x-raw-bayer", + "David Schleef "); +} + +static void +gst_rgb2bayer_class_init (GstRGB2BayerClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseTransformClass *base_transform_class = + GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->set_property = gst_rgb2bayer_set_property; + gobject_class->get_property = gst_rgb2bayer_get_property; + gobject_class->dispose = gst_rgb2bayer_dispose; + gobject_class->finalize = gst_rgb2bayer_finalize; + base_transform_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_rgb2bayer_transform_caps); + base_transform_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_rgb2bayer_get_unit_size); + base_transform_class->set_caps = GST_DEBUG_FUNCPTR (gst_rgb2bayer_set_caps); + base_transform_class->start = GST_DEBUG_FUNCPTR (gst_rgb2bayer_start); + base_transform_class->stop = GST_DEBUG_FUNCPTR (gst_rgb2bayer_stop); + base_transform_class->event = GST_DEBUG_FUNCPTR (gst_rgb2bayer_event); + base_transform_class->transform = GST_DEBUG_FUNCPTR (gst_rgb2bayer_transform); + base_transform_class->src_event = GST_DEBUG_FUNCPTR (gst_rgb2bayer_src_event); + +} + +static void +gst_rgb2bayer_init (GstRGB2Bayer * rgb2bayer, + GstRGB2BayerClass * rgb2bayer_class) +{ + +} + +void +gst_rgb2bayer_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstRGB2Bayer *rgb2bayer; + + g_return_if_fail (GST_IS_RGB_2_BAYER (object)); + rgb2bayer = GST_RGB_2_BAYER (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_rgb2bayer_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstRGB2Bayer *rgb2bayer; + + g_return_if_fail (GST_IS_RGB_2_BAYER (object)); + rgb2bayer = GST_RGB_2_BAYER (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_rgb2bayer_dispose (GObject * object) +{ + GstRGB2Bayer *rgb2bayer; + + g_return_if_fail (GST_IS_RGB_2_BAYER (object)); + rgb2bayer = GST_RGB_2_BAYER (object); + + /* clean up as possible. may be called multiple times */ + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +void +gst_rgb2bayer_finalize (GObject * object) +{ + GstRGB2Bayer *rgb2bayer; + + g_return_if_fail (GST_IS_RGB_2_BAYER (object)); + rgb2bayer = GST_RGB_2_BAYER (object); + + /* clean up object here */ + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +static GstCaps * +gst_rgb2bayer_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +{ + GstStructure *structure; + GstStructure *new_structure; + GstCaps *newcaps; + const GValue *value; + + GST_DEBUG_OBJECT (trans, "transforming caps (from) %" GST_PTR_FORMAT, caps); + + structure = gst_caps_get_structure (caps, 0); + + if (direction == GST_PAD_SRC) { + newcaps = gst_caps_new_simple ("video/x-raw-rgb", NULL); + } else { + newcaps = gst_caps_new_simple ("video/x-raw-bayer", NULL); + } + new_structure = gst_caps_get_structure (newcaps, 0); + + value = gst_structure_get_value (structure, "width"); + gst_structure_set_value (new_structure, "width", value); + + value = gst_structure_get_value (structure, "height"); + gst_structure_set_value (new_structure, "height", value); + + value = gst_structure_get_value (structure, "framerate"); + gst_structure_set_value (new_structure, "framerate", value); + + GST_DEBUG_OBJECT (trans, "transforming caps (into) %" GST_PTR_FORMAT, + newcaps); + + return newcaps; +} + +static gboolean +gst_rgb2bayer_get_unit_size (GstBaseTransform * trans, GstCaps * caps, + guint * size) +{ + GstStructure *structure; + int width; + int height; + int pixsize; + const char *name; + + structure = gst_caps_get_structure (caps, 0); + + if (gst_structure_get_int (structure, "width", &width) && + gst_structure_get_int (structure, "height", &height)) { + name = gst_structure_get_name (structure); + /* Our name must be either video/x-raw-bayer video/x-raw-rgb */ + if (g_str_equal (name, "video/x-raw-bayer")) { + *size = width * height; + return TRUE; + } else { + /* For output, calculate according to format */ + if (gst_structure_get_int (structure, "bpp", &pixsize)) { + *size = width * height * (pixsize / 8); + return TRUE; + } + } + + } + + return FALSE; +} + +static gboolean +gst_rgb2bayer_set_caps (GstBaseTransform * trans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstRGB2Bayer *rgb2bayer = GST_RGB_2_BAYER (trans); + GstStructure *structure; + + GST_DEBUG ("in caps %" GST_PTR_FORMAT " out caps %" GST_PTR_FORMAT, incaps, + outcaps); + + structure = gst_caps_get_structure (incaps, 0); + + gst_structure_get_int (structure, "width", &rgb2bayer->width); + gst_structure_get_int (structure, "height", &rgb2bayer->height); + + return TRUE; +} + +static gboolean +gst_rgb2bayer_start (GstBaseTransform * trans) +{ + + return TRUE; +} + +static gboolean +gst_rgb2bayer_stop (GstBaseTransform * trans) +{ + + return TRUE; +} + +static gboolean +gst_rgb2bayer_event (GstBaseTransform * trans, GstEvent * event) +{ + + return TRUE; +} + +static GstFlowReturn +gst_rgb2bayer_transform (GstBaseTransform * trans, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + GstRGB2Bayer *rgb2bayer = GST_RGB_2_BAYER (trans); + guint8 *dest; + guint8 *src; + int i, j; + int height = rgb2bayer->height; + int width = rgb2bayer->width; + + dest = GST_BUFFER_DATA (outbuf); + src = GST_BUFFER_DATA (inbuf); + + for (j = 0; j < height; j++) { + guint8 *dest_line = dest + width * j; + guint8 *src_line = src + width * 4 * j; + + for (i = 0; i < width; i++) { + if ((i & 1) == 0 && (j & 1) == 0) { + dest_line[i] = src_line[i * 4 + 3]; + } else if ((i & 1) == 1 && (j & 1) == 1) { + dest_line[i] = src_line[i * 4 + 1]; + } else { + dest_line[i] = src_line[i * 4 + 2]; + } + } + } + + return GST_FLOW_OK; +} + +static gboolean +gst_rgb2bayer_src_event (GstBaseTransform * trans, GstEvent * event) +{ + + return TRUE; +} diff --git a/gst/bayer/gstrgb2bayer.h b/gst/bayer/gstrgb2bayer.h new file mode 100644 index 0000000000..c09b3518da --- /dev/null +++ b/gst/bayer/gstrgb2bayer.h @@ -0,0 +1,53 @@ +/* GStreamer + * Copyright (C) 2010 FIXME + * + * 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 _GST_RGB_2_BAYER_H_ +#define _GST_RGB_2_BAYER_H_ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_RGB_2_BAYER (gst_rgb2bayer_get_type()) +#define GST_RGB_2_BAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RGB_2_BAYER,GstRGB2Bayer)) +#define GST_RGB_2_BAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RGB_2_BAYER,GstRGB2BayerClass)) +#define GST_IS_RGB_2_BAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RGB_2_BAYER)) +#define GST_IS_RGB_2_BAYER_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RGB_2_BAYER)) + +typedef struct _GstRGB2Bayer GstRGB2Bayer; +typedef struct _GstRGB2BayerClass GstRGB2BayerClass; + +struct _GstRGB2Bayer +{ + GstBaseTransform base_rgb2bayer; + + int width, height; +}; + +struct _GstRGB2BayerClass +{ + GstBaseTransformClass base_rgb2bayer_class; +}; + +GType gst_rgb2bayer_get_type (void); + +G_END_DECLS + +#endif