From 59b6d933da390d7954f1f0a18d5708fc65a3689d Mon Sep 17 00:00:00 2001 From: Lutz Mueller Date: Thu, 10 Sep 2009 08:23:22 +0200 Subject: [PATCH] pnm: Add PNM encoder and decoder elements Fixes bug #164870. --- configure.ac | 2 + gst/pnm/Makefile.am | 8 ++ gst/pnm/gstpnm.c | 98 ++++++++++++++++++++ gst/pnm/gstpnmdec.c | 194 ++++++++++++++++++++++++++++++++++++++++ gst/pnm/gstpnmdec.h | 55 ++++++++++++ gst/pnm/gstpnmenc.c | 170 +++++++++++++++++++++++++++++++++++ gst/pnm/gstpnmenc.h | 53 +++++++++++ gst/pnm/gstpnmutils.c | 203 ++++++++++++++++++++++++++++++++++++++++++ gst/pnm/gstpnmutils.h | 86 ++++++++++++++++++ 9 files changed, 869 insertions(+) create mode 100644 gst/pnm/Makefile.am create mode 100644 gst/pnm/gstpnm.c create mode 100644 gst/pnm/gstpnmdec.c create mode 100644 gst/pnm/gstpnmdec.h create mode 100644 gst/pnm/gstpnmenc.c create mode 100644 gst/pnm/gstpnmenc.h create mode 100644 gst/pnm/gstpnmutils.c create mode 100644 gst/pnm/gstpnmutils.h diff --git a/configure.ac b/configure.ac index 438b2cd5cb..19898247b6 100644 --- a/configure.ac +++ b/configure.ac @@ -281,6 +281,7 @@ AG_GST_CHECK_PLUGIN(mxf) AG_GST_CHECK_PLUGIN(nsf) AG_GST_CHECK_PLUGIN(nuvdemux) AG_GST_CHECK_PLUGIN(pcapparse) +AG_GST_CHECK_PLUGIN(pnm) AG_GST_CHECK_PLUGIN(qtmux) AG_GST_CHECK_PLUGIN(rawparse) AG_GST_CHECK_PLUGIN(real) @@ -1730,6 +1731,7 @@ gst/mxf/Makefile gst/nsf/Makefile gst/nuvdemux/Makefile gst/pcapparse/Makefile +gst/pnm/Makefile gst/qtmux/Makefile gst/rawparse/Makefile gst/real/Makefile diff --git a/gst/pnm/Makefile.am b/gst/pnm/Makefile.am new file mode 100644 index 0000000000..a2463c939f --- /dev/null +++ b/gst/pnm/Makefile.am @@ -0,0 +1,8 @@ +plugin_LTLIBRARIES = libgstpnm.la + +libgstpnm_la_SOURCES = gstpnmutils.c gstpnm.c gstpnmdec.c gstpnmenc.c +libgstpnm_la_CFLAGS = $(GST_CFLAGS) +libgstpnm_la_LIBADD = $(GST_LIBS) +libgstpnm_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = gstpnmdec.h gstpnmutils.h gstpnmenc.h diff --git a/gst/pnm/gstpnm.c b/gst/pnm/gstpnm.c new file mode 100644 index 0000000000..36d0e29cfd --- /dev/null +++ b/gst/pnm/gstpnm.c @@ -0,0 +1,98 @@ +/* GStreamer + * + * 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 "gstpnmdec.h" +#include "gstpnmenc.h" +#include "gstpnmutils.h" + +#include +#include +#include + +#include + +static GstStaticCaps bitmap_caps = GST_STATIC_CAPS (MIME_BM); +static GstStaticCaps graymap_caps = GST_STATIC_CAPS (MIME_GM); +static GstStaticCaps pixmap_caps = GST_STATIC_CAPS (MIME_PM); + +#define BITMAP_CAPS (gst_static_caps_get (&bitmap_caps)) +#define GRAYMAP_CAPS (gst_static_caps_get (&graymap_caps)) +#define PIXMAP_CAPS (gst_static_caps_get (&pixmap_caps)) + +static void +gst_my_typefind_function (GstTypeFind * tf, gpointer d) +{ + GstPnmInfoMngrResult r = GST_PNM_INFO_MNGR_RESULT_READING; + GstPnmInfoMngr mngr = { 0, }; + guint i; + guint8 *data = NULL; + + for (i = 0; r == GST_PNM_INFO_MNGR_RESULT_READING; i++) { + data = gst_type_find_peek (tf, i, 1); + if (!data) + break; + r = gst_pnm_info_mngr_scan (&mngr, data, 1); + } + switch (r) { + case GST_PNM_INFO_MNGR_RESULT_READING: + case GST_PNM_INFO_MNGR_RESULT_FAILED: + return; + case GST_PNM_INFO_MNGR_RESULT_FINISHED: + switch (mngr.info.type) { + case GST_PNM_TYPE_BITMAP_ASCII: + case GST_PNM_TYPE_BITMAP_RAW: + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, BITMAP_CAPS); + return; + case GST_PNM_TYPE_GRAYMAP_ASCII: + case GST_PNM_TYPE_GRAYMAP_RAW: + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, GRAYMAP_CAPS); + return; + case GST_PNM_TYPE_PIXMAP_ASCII: + case GST_PNM_TYPE_PIXMAP_RAW: + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, PIXMAP_CAPS); + return; + } + } +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + static gchar *exts[] = { "pnm", NULL }; + + if (!gst_type_find_register (plugin, "", GST_RANK_PRIMARY, + gst_my_typefind_function, exts, gst_caps_new_simple (MIME_ALL, NULL), + NULL, NULL)) + return FALSE; + + if (!gst_element_register (plugin, "pnmdec", GST_RANK_PRIMARY, + GST_TYPE_PNMDEC)) + return FALSE; + if (!gst_element_register (plugin, "pnmenc", GST_RANK_PRIMARY, + GST_TYPE_PNMENC)) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "pnm", + "PNM plugin", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN) diff --git a/gst/pnm/gstpnmdec.c b/gst/pnm/gstpnmdec.c new file mode 100644 index 0000000000..c02ad3c6b0 --- /dev/null +++ b/gst/pnm/gstpnmdec.c @@ -0,0 +1,194 @@ +/* GStreamer + * + * 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. + */ + +/** + * SECTION:element-pnmdec + * + * Decodes pnm images. + * + * + * Example launch line + * |[ + * gst-launch filesrc location=test.pnm ! pnmdec ! ximagesink + * ]| The above pipeline reads a pnm file and renders it to the screen. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstpnmdec.h" +#include "gstpnmutils.h" + +#include + +#include + +static GstElementDetails pnmdec_details = GST_ELEMENT_DETAILS ("PNM converter", + "Codec/Decoder/Image", "Decodes PNM format", + "Lutz Mueller "); + +static GstElementClass *parent_class; + +static GstStaticPadTemplate gst_pnmdec_src_pad_template = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-rgb, bpp = (int) 24, " + "width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]")); + +static GstStaticPadTemplate gst_pnmdec_sink_pad_template = +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS (MIME_ALL)); + +static GstFlowReturn +gst_pnmdec_chain (GstPad * pad, GstBuffer * data) +{ + GstPnmdec *s = GST_PNMDEC (gst_pad_get_parent (pad)); + GstPad *src = gst_element_get_static_pad (GST_ELEMENT (s), "src"); + GstBuffer *buf; + GstCaps *caps = NULL; + GstFlowReturn r = GST_FLOW_OK; + guint8 offset = 0; + + if (!(s->mngr.info.fields & GST_PNM_INFO_FIELDS_ALL)) { + switch (gst_pnm_info_mngr_scan (&s->mngr, GST_BUFFER_DATA (data), + GST_BUFFER_SIZE (data))) { + case GST_PNM_INFO_MNGR_RESULT_FAILED: + gst_buffer_unref (data); + return GST_FLOW_ERROR; + case GST_PNM_INFO_MNGR_RESULT_READING: + gst_buffer_unref (data); + return GST_FLOW_OK; + case GST_PNM_INFO_MNGR_RESULT_FINISHED: + offset = s->mngr.data_offset; + caps = gst_pad_get_caps (src); + gst_caps_set_simple (caps, + "width", G_TYPE_INT, s->mngr.info.width, + "height", G_TYPE_INT, s->mngr.info.height, NULL); + if (!gst_pad_set_caps (src, caps)) { + gst_caps_unref (caps); + return GST_FLOW_ERROR; + } + gst_caps_unref (caps); + switch (s->mngr.info.type) { + case GST_PNM_TYPE_BITMAP_RAW: + case GST_PNM_TYPE_BITMAP_ASCII: + case GST_PNM_TYPE_GRAYMAP_RAW: + case GST_PNM_TYPE_GRAYMAP_ASCII: + s->size = s->mngr.info.width * s->mngr.info.height * 1; + break; + case GST_PNM_TYPE_PIXMAP_RAW: + case GST_PNM_TYPE_PIXMAP_ASCII: + s->size = s->mngr.info.width * s->mngr.info.height * 3; + break; + } + } + } + + if (offset == GST_BUFFER_SIZE (data)) + return GST_FLOW_OK; + + /* If we got the whole image, just push the buffer. */ + if (GST_BUFFER_SIZE (data) - offset == s->size) { + buf = gst_buffer_create_sub (data, offset, s->size); + gst_buffer_unref (data); + memset (&s->mngr, 0, sizeof (GstPnmInfoMngr)); + s->size = 0; + gst_buffer_set_caps (buf, GST_PAD_CAPS (src)); + return gst_pad_push (src, buf); + } + + /* We didn't get the whole image. */ + if (!s->buf) { + s->buf = gst_buffer_create_sub (data, offset, + GST_BUFFER_SIZE (data) - offset); + } else { + buf = gst_buffer_span (s->buf, 0, data, + GST_BUFFER_SIZE (s->buf) + GST_BUFFER_SIZE (data) - offset); + gst_buffer_unref (s->buf); + s->buf = buf; + } + if (!s->buf) + return GST_FLOW_ERROR; + + /* Do we now have the full image? If yes, push. */ + if (GST_BUFFER_SIZE (s->buf) == s->size) { + gst_buffer_set_caps (s->buf, GST_PAD_CAPS (src)); + r = gst_pad_push (src, s->buf); + s->buf = NULL; + memset (&s->mngr, 0, sizeof (GstPnmInfoMngr)); + s->size = 0; + } + + return r; +} + +static void +gst_pnmdec_finalize (GObject * object) +{ + GstPnmdec *dec = GST_PNMDEC (object); + + if (dec->buf) { + gst_buffer_unref (dec->buf); + dec->buf = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_pnmdec_init (GstPnmdec * s, GstPnmdecClass * klass) +{ + GstPad *pad; + + pad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_pnmdec_sink_pad_template), "sink"); + gst_pad_set_chain_function (pad, gst_pnmdec_chain); + gst_element_add_pad (GST_ELEMENT (s), pad); + + pad = + gst_pad_new_from_template (gst_static_pad_template_get + (&gst_pnmdec_src_pad_template), "src"); + gst_pad_use_fixed_caps (pad); + gst_element_add_pad (GST_ELEMENT (s), pad); +} + +static void +gst_pnmdec_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_pnmdec_sink_pad_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_pnmdec_src_pad_template)); + gst_element_class_set_details (element_class, &pnmdec_details); +} + +static void +gst_pnmdec_class_init (GstPnmdecClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_pnmdec_finalize; +} + +GST_BOILERPLATE (GstPnmdec, gst_pnmdec, GstElement, GST_TYPE_ELEMENT) diff --git a/gst/pnm/gstpnmdec.h b/gst/pnm/gstpnmdec.h new file mode 100644 index 0000000000..318ba25889 --- /dev/null +++ b/gst/pnm/gstpnmdec.h @@ -0,0 +1,55 @@ +/* GStreamer + * + * 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_PNMDEC_H__ +#define __GST_PNMDEC_H__ + +#include + +#include "gstpnmutils.h" + +G_BEGIN_DECLS + +#define GST_TYPE_PNMDEC (gst_pnmdec_get_type()) +#define GST_PNMDEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PNMDEC,GstPnmdec)) +#define GST_PNMDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PNMDEC,GstPnmdec)) +#define GST_IS_PNMDEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PNMDEC)) +#define GST_IS_PNMDEC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PNMDEC)) + +typedef struct _GstPnmdec GstPnmdec; +typedef struct _GstPnmdecClass GstPnmdecClass; + +struct _GstPnmdec +{ + GstElement element; + + GstPnmInfoMngr mngr; + guint size; + GstBuffer *buf; +}; + +struct _GstPnmdecClass +{ + GstElementClass parent_class; +}; + +GType gst_pnmdec_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GST_PNMDEC_H__ */ diff --git a/gst/pnm/gstpnmenc.c b/gst/pnm/gstpnmenc.c new file mode 100644 index 0000000000..56348bd539 --- /dev/null +++ b/gst/pnm/gstpnmenc.c @@ -0,0 +1,170 @@ +/* GStreamer + * + * 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. + */ + +/** + * SECTION:element-pnmenc + * + * Encodes pnm images. + * + * + * Example launch line + * |[ + * gst-launch videotestsrc num_buffers=1 ! pnmenc ! filesink location=test.pnm + * ]| The above pipeline writes a test pnm file. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstpnmenc.h" +#include "gstpnmutils.h" + +#include + +#include + +static GstElementDetails pnmenc_details = +GST_ELEMENT_DETAILS ("PNM converter", "Codec/Encoder/Image", + "Encodes in PNM format", + "Lutz Mueller "); + +static GstStaticPadTemplate sink_pad_template = +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-rgb, bpp = (int) 24, " + "width = (int) [ 1, MAX ], height = (int) [ 1, MAX ]")); + +static GstStaticPadTemplate src_pad_template = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS (MIME_ALL)); + +static GstFlowReturn +gst_pnmenc_chain (GstPad * pad, GstBuffer * buf) +{ + GstPnmenc *s = GST_PNMENC (gst_pad_get_parent (pad)); + GstPad *src = gst_element_get_static_pad (GST_ELEMENT (s), "src"); + GstFlowReturn r; + gchar *header; + GstBuffer *out; + + /* The caps on the source may not be set. */ + if (!GST_PAD_CAPS (src)) { + GstCaps *caps = gst_caps_new_simple (MIME_PM, NULL); + gst_pad_set_caps (src, caps); + gst_caps_unref (caps); + } + + /* Assumption: One buffer, one image. That is, always first write header. */ + header = g_strdup_printf ("P%i\n%i %i\n%i\n", + s->info.type, s->info.width, s->info.height, s->info.max); + out = gst_buffer_new (); + gst_buffer_set_data (out, (guchar *) header, strlen (header)); + gst_buffer_set_caps (out, GST_PAD_CAPS (src)); + if ((r = gst_pad_push (src, buf)) != GST_FLOW_OK) + return r; + + /* Pass through the data. */ + gst_buffer_set_caps (buf, GST_PAD_CAPS (src)); + return gst_pad_push (src, buf); +} + +static gboolean +gst_pnmenc_setcaps_func_sink (GstPad * pad, GstCaps * caps) +{ + GstPnmenc *s = GST_PNMENC (gst_pad_get_parent (pad)); + GstStructure *structure = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (structure, "width", (int *) &s->info.width) || + !gst_structure_get_int (structure, "height", (int *) &s->info.height)) + return FALSE; + s->info.fields = GST_PNM_INFO_FIELDS_WIDTH | GST_PNM_INFO_FIELDS_HEIGHT; + + return TRUE; +} + +static GstPadLinkReturn +gst_pnmenc_setcaps_func_src (GstPad * pad, GstCaps * caps) +{ + GstPnmenc *s = GST_PNMENC (gst_pad_get_parent (pad)); + guint i; + + s->info.fields &= ~GST_PNM_INFO_FIELDS_TYPE; + for (i = 0; i < gst_caps_get_size (caps); i++) { + GstStructure *structure = gst_caps_get_structure (caps, i); + const gchar *mime = gst_structure_get_name (structure); + + if (!strcmp (mime, MIME_BM)) { + s->info.type = GST_PNM_TYPE_BITMAP_RAW; + break; + } + if (!strcmp (mime, MIME_GM)) { + s->info.type = GST_PNM_TYPE_GRAYMAP_RAW; + break; + } + if (!strcmp (mime, MIME_PM) || !strcmp (mime, MIME_AM)) { + s->info.type = GST_PNM_TYPE_PIXMAP_RAW; + break; + } + } + if (i == gst_caps_get_size (caps)) + return FALSE; + s->info.max = 255; + s->info.fields |= GST_PNM_INFO_FIELDS_TYPE | GST_PNM_INFO_FIELDS_MAX; + + return TRUE; +} + +static void +gst_pnmenc_init (GstPnmenc * s, GstPnmencClass * klass) +{ + GstPad *pad; + + pad = + gst_pad_new_from_template (gst_static_pad_template_get + (&sink_pad_template), "sink"); + gst_pad_set_setcaps_function (pad, gst_pnmenc_setcaps_func_sink); + gst_pad_set_chain_function (pad, gst_pnmenc_chain); + gst_element_add_pad (GST_ELEMENT (s), pad); + + pad = + gst_pad_new_from_template (gst_static_pad_template_get + (&src_pad_template), "src"); + gst_pad_set_setcaps_function (pad, gst_pnmenc_setcaps_func_src); + gst_element_add_pad (GST_ELEMENT (s), pad); +} + +static void +gst_pnmenc_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 (&sink_pad_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_pad_template)); + gst_element_class_set_details (element_class, &pnmenc_details); +} + +static void +gst_pnmenc_class_init (GstPnmencClass * klass) +{ + /* Nothing to see here. Move along. */ +} + +GST_BOILERPLATE (GstPnmenc, gst_pnmenc, GstElement, GST_TYPE_ELEMENT) diff --git a/gst/pnm/gstpnmenc.h b/gst/pnm/gstpnmenc.h new file mode 100644 index 0000000000..152414168a --- /dev/null +++ b/gst/pnm/gstpnmenc.h @@ -0,0 +1,53 @@ +/* GStreamer + * + * 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_PNMENC_H__ +#define __GST_PNMENC_H__ + +#include + +#include "gstpnmutils.h" + +G_BEGIN_DECLS + +#define GST_TYPE_PNMENC (gst_pnmenc_get_type()) +#define GST_PNMENC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PNMENC,GstPnmenc)) +#define GST_PNMENC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PNMENC,GstPnmenc)) +#define GST_IS_PNMENC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PNMENC)) +#define GST_IS_PNMENC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PNMENC)) + +typedef struct _GstPnmenc GstPnmenc; +typedef struct _GstPnmencClass GstPnmencClass; + +struct _GstPnmenc +{ + GstElement element; + + GstPnmInfo info; +}; + +struct _GstPnmencClass +{ + GstElementClass parent_class; +}; + +GType gst_pnmenc_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GST_PNMENC_H__ */ diff --git a/gst/pnm/gstpnmutils.c b/gst/pnm/gstpnmutils.c new file mode 100644 index 0000000000..a0c8f384cc --- /dev/null +++ b/gst/pnm/gstpnmutils.c @@ -0,0 +1,203 @@ +/* GStreamer + * + * 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. + */ + +#include "gstpnmutils.h" + +GstPnmInfoMngrResult +gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf, + guint buf_len) +{ + guint i = 0; + + g_return_val_if_fail (mngr != NULL, GST_PNM_INFO_MNGR_RESULT_FAILED); + g_return_val_if_fail (buf || !buf_len, GST_PNM_INFO_MNGR_RESULT_FAILED); + + if (!buf_len) + return (mngr->info.fields == + GST_PNM_INFO_FIELDS_ALL) ? GST_PNM_INFO_MNGR_RESULT_FINISHED : + GST_PNM_INFO_MNGR_RESULT_READING; + + switch (mngr->state) { + case GST_PNM_INFO_MNGR_STATE_COMMENT: + for (i = 0; (i < buf_len) && (buf[i] != '\n'); i++); + if (i == buf_len) + return GST_PNM_INFO_MNGR_RESULT_READING; + mngr->state = GST_PNM_INFO_MNGR_STATE_NONE; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + case GST_PNM_INFO_MNGR_STATE_WHITE_SPACE: + for (i = 0; (i < buf_len) && ((buf[i] == ' ') || (buf[i] == '\t') + || (buf[i] == '\n')); i++); + if (i == buf_len) + return GST_PNM_INFO_MNGR_RESULT_READING; + mngr->state = GST_PNM_INFO_MNGR_STATE_NONE; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + case GST_PNM_INFO_MNGR_STATE_NONE: + switch (buf[i++]) { + case '#': + mngr->state = GST_PNM_INFO_MNGR_STATE_COMMENT; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + case ' ': + case '\t': + case '\n': + mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + case 'P': + if (mngr->info.fields & GST_PNM_INFO_FIELDS_TYPE) + return GST_PNM_INFO_MNGR_RESULT_FAILED; + mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_TYPE; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (mngr->info.fields & GST_PNM_INFO_FIELDS_MAX) + return GST_PNM_INFO_MNGR_RESULT_FINISHED; + if (mngr->info.fields & GST_PNM_INFO_FIELDS_HEIGHT) { + mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_MAX; + return gst_pnm_info_mngr_scan (mngr, buf, buf_len); + } + if (mngr->info.fields & GST_PNM_INFO_FIELDS_WIDTH) { + mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT; + return gst_pnm_info_mngr_scan (mngr, buf, buf_len); + } + mngr->state = GST_PNM_INFO_MNGR_STATE_DATA_WIDTH; + return gst_pnm_info_mngr_scan (mngr, buf, buf_len); + default: + return GST_PNM_INFO_MNGR_RESULT_FAILED; + } + case GST_PNM_INFO_MNGR_STATE_DATA_TYPE: + switch (buf[i++]) { + case '1': + mngr->info.type = GST_PNM_TYPE_BITMAP_ASCII; + break; + case '2': + mngr->info.type = GST_PNM_TYPE_GRAYMAP_ASCII; + break; + case '3': + mngr->info.type = GST_PNM_TYPE_PIXMAP_ASCII; + break; + case '4': + mngr->info.type = GST_PNM_TYPE_BITMAP_RAW; + break; + case '5': + mngr->info.type = GST_PNM_TYPE_GRAYMAP_RAW; + break; + case '6': + mngr->info.type = GST_PNM_TYPE_PIXMAP_RAW; + break; + default: + return GST_PNM_INFO_MNGR_RESULT_FAILED; + } + mngr->info.fields |= GST_PNM_INFO_FIELDS_TYPE; + mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE; + if (i == buf_len) + return GST_PNM_INFO_MNGR_RESULT_READING; + mngr->info.width = mngr->info.height = mngr->info.max = 0; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + case GST_PNM_INFO_MNGR_STATE_DATA_WIDTH: + if ((buf[i] < '0') || (buf[i] > '9')) { + switch (buf[i]) { + case '\n': + case '\t': + case ' ': + mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + default: + return GST_PNM_INFO_MNGR_RESULT_FAILED; + } + } + mngr->info.width *= 10; + mngr->info.width += buf[i++] - 0x030; + mngr->info.fields |= GST_PNM_INFO_FIELDS_WIDTH; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + case GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT: + if ((buf[i] < '0') || (buf[i] > '9')) { + switch (buf[i]) { + case '\n': + case '\t': + case ' ': + mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + default: + return GST_PNM_INFO_MNGR_RESULT_FAILED; + } + } + mngr->info.height *= 10; + mngr->info.height += buf[i++] - 0x030; + mngr->info.fields |= GST_PNM_INFO_FIELDS_HEIGHT; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + case GST_PNM_INFO_MNGR_STATE_DATA_MAX: + if ((buf[i] < '0') || (buf[i] > '9')) { + switch (buf[i]) { + case '\n': + case '\t': + case ' ': + mngr->data_offset += i + 1; + return GST_PNM_INFO_MNGR_RESULT_FINISHED; + default: + return GST_PNM_INFO_MNGR_RESULT_FAILED; + } + } + mngr->info.max *= 10; + mngr->info.max += buf[i++] - 0x030; + mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX; + mngr->data_offset += i; + return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i); + } + return GST_PNM_INFO_MNGR_RESULT_FAILED; +} + +GType +gst_pnm_type_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + {GST_PNM_TYPE_BITMAP_RAW, "GST_PNM_TYPE_BITMAP_RAW", MIME_BM " (ascii)"}, + {GST_PNM_TYPE_GRAYMAP_ASCII, "GST_PNM_TYPE_BITMAP_ASCII", + MIME_BM " (raw)"}, + {GST_PNM_TYPE_GRAYMAP_RAW, "GST_PNM_TYPE_GRAYMAP_RAW", + MIME_GM " (ascii)"}, + {GST_PNM_TYPE_GRAYMAP_ASCII, "GST_PNM_TYPE_GRAYMAP_ASCII", + MIME_GM " (raw)"}, + {GST_PNM_TYPE_PIXMAP_RAW, "GST_PNM_TYPE_PIXMAP_RAW", MIME_PM " (ascii)"}, + {GST_PNM_TYPE_PIXMAP_ASCII, "GST_PNM_TYPE_PIXMAP_ASCII", + MIME_PM " (raw)"}, + {0, NULL, NULL} + }; + etype = g_enum_register_static ("GstPnmdecType", values); + } + return etype; +} diff --git a/gst/pnm/gstpnmutils.h b/gst/pnm/gstpnmutils.h new file mode 100644 index 0000000000..b0afb5fc2f --- /dev/null +++ b/gst/pnm/gstpnmutils.h @@ -0,0 +1,86 @@ +/* GStreamer + * + * 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_PNM_UTILS_H__ +#define __GST_PNM_UTILS_H__ + +#include +#include + +#define MIME_BM "image/x-image-bitmap" +#define MIME_GM "image/x-image-graymap" +#define MIME_PM "image/x-image-pixmap" +#define MIME_AM "image/x-image-anymap" +#define MIME_ALL MIME_BM "; " MIME_GM "; " MIME_PM "; " MIME_AM + +typedef enum +{ + GST_PNM_INFO_FIELDS_TYPE = 1 << 0, + GST_PNM_INFO_FIELDS_WIDTH = 1 << 1, + GST_PNM_INFO_FIELDS_HEIGHT = 1 << 2, + GST_PNM_INFO_FIELDS_MAX = 1 << 3 +} GstPnmInfoFields; + +#define GST_PNM_INFO_FIELDS_ALL (GST_PNM_INFO_FIELDS_TYPE | GST_PNM_INFO_FIELDS_WIDTH | GST_PNM_INFO_FIELDS_HEIGHT | GST_PNM_INFO_FIELDS_MAX) + +typedef enum +{ + GST_PNM_TYPE_BITMAP_ASCII = 1, + GST_PNM_TYPE_GRAYMAP_ASCII = 2, + GST_PNM_TYPE_PIXMAP_ASCII = 3, + GST_PNM_TYPE_BITMAP_RAW = 4, + GST_PNM_TYPE_GRAYMAP_RAW = 5, + GST_PNM_TYPE_PIXMAP_RAW = 6 +} GstPnmType; +GType gst_pnm_type_get_type (void); + +typedef struct +{ + GstPnmInfoFields fields; + GstPnmType type; + guint width, height, max; +} GstPnmInfo; + +typedef enum +{ + GST_PNM_INFO_MNGR_STATE_NONE = 0, + GST_PNM_INFO_MNGR_STATE_DATA_TYPE, + GST_PNM_INFO_MNGR_STATE_DATA_WIDTH, + GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT, + GST_PNM_INFO_MNGR_STATE_DATA_MAX, + GST_PNM_INFO_MNGR_STATE_COMMENT, + GST_PNM_INFO_MNGR_STATE_WHITE_SPACE +} GstPnmInfoMngrState; + +typedef struct +{ + GstPnmInfoMngrState state; + GstPnmInfo info; + guint8 data_offset; +} GstPnmInfoMngr; + +typedef enum +{ + GST_PNM_INFO_MNGR_RESULT_FAILED, + GST_PNM_INFO_MNGR_RESULT_READING, + GST_PNM_INFO_MNGR_RESULT_FINISHED +} GstPnmInfoMngrResult; + +GstPnmInfoMngrResult gst_pnm_info_mngr_scan (GstPnmInfoMngr *, const guint8 *, guint); + +#endif /* __GST_PNM_UTILS_H__ */