ext/libpng/: Added png decoder.

Original commit message from CVS:
* ext/libpng/Makefile.am:
* ext/libpng/gstpng.c: (plugin_init):
* ext/libpng/gstpngdec.c: (user_error_fn), (user_warning_fn),
(gst_pngdec_get_type), (gst_pngdec_base_init),
(gst_pngdec_class_init), (gst_pngdec_sinklink), (gst_pngdec_init),
(gst_pngdec_src_getcaps), (user_read_data), (gst_pngdec_chain):
* ext/libpng/gstpngdec.h:
Added png decoder.
This commit is contained in:
Wim Taymans 2004-07-16 10:56:31 +00:00
parent dfb55453e4
commit e4908795d7
5 changed files with 444 additions and 2 deletions

View file

@ -1,3 +1,14 @@
2004-07-16 Wim Taymans <wim@fluendo.com>
* ext/libpng/Makefile.am:
* ext/libpng/gstpng.c: (plugin_init):
* ext/libpng/gstpngdec.c: (user_error_fn), (user_warning_fn),
(gst_pngdec_get_type), (gst_pngdec_base_init),
(gst_pngdec_class_init), (gst_pngdec_sinklink), (gst_pngdec_init),
(gst_pngdec_src_getcaps), (user_read_data), (gst_pngdec_chain):
* ext/libpng/gstpngdec.h:
Added png decoder.
2004-07-16 Julien MOUTTE <julien@moutte.net> 2004-07-16 Julien MOUTTE <julien@moutte.net>
* sys/ximage/ximagesink.c: (gst_ximagesink_handle_xerror), * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xerror),
@ -15,6 +26,16 @@
data to be coherent with the buffer alloc mechanism. Investigated the data to be coherent with the buffer alloc mechanism. Investigated the
image destruction code to be sure that everything gets freed correctly. image destruction code to be sure that everything gets freed correctly.
2004-07-16 Wim Taymans <wim@fluendo.com>
* gst-libs/gst/riff/riff-read.c:
(gst_riff_read_strf_vids_with_data),
(gst_riff_read_strf_auds_with_data):
* gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query),
(gst_avi_demux_add_stream), (gst_avi_demux_stream_header):
Make sure we don't create 0 sized subbufers in riff-read.
Signal the no more pads signal after reading the avi header.
2004-07-16 Wim Taymans <wim@fluendo.com> 2004-07-16 Wim Taymans <wim@fluendo.com>
* gst/playback/gstdecodebin.c: (gst_decode_bin_get_type), * gst/playback/gstdecodebin.c: (gst_decode_bin_get_type),

View file

@ -1,9 +1,9 @@
plugin_LTLIBRARIES = libgstpng.la plugin_LTLIBRARIES = libgstpng.la
libgstpng_la_SOURCES = gstpng.c gstpngenc.c libgstpng_la_SOURCES = gstpng.c gstpngdec.c gstpngenc.c
libgstpng_la_CFLAGS = $(GST_CFLAGS) libgstpng_la_CFLAGS = $(GST_CFLAGS)
libgstpng_la_LIBADD = $(GST_LIBS) $(LIBPNG_LIBS) libgstpng_la_LIBADD = $(GST_LIBS) $(LIBPNG_LIBS)
libgstpng_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstpng_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
noinst_HEADERS = gstpngenc.h noinst_HEADERS = gstpngdec.h gstpngenc.h

View file

@ -23,11 +23,16 @@
#include <string.h> #include <string.h>
#include <gst/gst.h> #include <gst/gst.h>
#include "gstpngdec.h"
#include "gstpngenc.h" #include "gstpngenc.h"
static gboolean static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
if (!gst_element_register (plugin, "pngdec", GST_RANK_PRIMARY,
GST_TYPE_PNGDEC))
return FALSE;
if (!gst_element_register (plugin, "pngenc", GST_RANK_NONE, GST_TYPE_PNGENC)) if (!gst_element_register (plugin, "pngenc", GST_RANK_NONE, GST_TYPE_PNGENC))
return FALSE; return FALSE;

342
ext/libpng/gstpngdec.c Normal file
View file

@ -0,0 +1,342 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* 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 <string.h>
#include <gst/gst.h>
#include "gstpngdec.h"
#include <gst/video/video.h>
static GstElementDetails gst_pngdec_details = {
"PNG decoder",
"Codec/Decoder/Image",
"Decode a png video frame to a raw image",
"Wim Taymans <wim@fluendo.com>",
};
/* Filter signals and args */
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
ARG_0
};
static void gst_pngdec_base_init (gpointer g_class);
static void gst_pngdec_class_init (GstPngDecClass * klass);
static void gst_pngdec_init (GstPngDec * pngdec);
static void gst_pngdec_chain (GstPad * pad, GstData * _data);
static GstCaps *gst_pngdec_src_getcaps (GstPad * pad);
static GstElementClass *parent_class = NULL;
static void
user_error_fn (png_structp png_ptr, png_const_charp error_msg)
{
g_warning ("%s", error_msg);
}
static void
user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
{
g_warning ("%s", warning_msg);
}
GType
gst_pngdec_get_type (void)
{
static GType pngdec_type = 0;
if (!pngdec_type) {
static const GTypeInfo pngdec_info = {
sizeof (GstPngDecClass),
gst_pngdec_base_init,
NULL,
(GClassInitFunc) gst_pngdec_class_init,
NULL,
NULL,
sizeof (GstPngDec),
0,
(GInstanceInitFunc) gst_pngdec_init,
};
pngdec_type = g_type_register_static (GST_TYPE_ELEMENT, "GstPngDec",
&pngdec_info, 0);
}
return pngdec_type;
}
static GstStaticPadTemplate gst_pngdec_src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_RGB)
);
static GstStaticPadTemplate gst_pngdec_sink_pad_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-png, "
"width = (int) [ 16, 4096 ], "
"height = (int) [ 16, 4096 ], " "framerate = (double) [ 0.0, MAX ]")
);
static void
gst_pngdec_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_pngdec_src_pad_template));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_pngdec_sink_pad_template));
gst_element_class_set_details (element_class, &gst_pngdec_details);
}
static void
gst_pngdec_class_init (GstPngDecClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
}
static GstPadLinkReturn
gst_pngdec_sinklink (GstPad * pad, const GstCaps * caps)
{
GstPngDec *pngdec;
GstStructure *structure;
pngdec = GST_PNGDEC (gst_pad_get_parent (pad));
structure = gst_caps_get_structure (caps, 0);
gst_structure_get_double (structure, "framerate", &pngdec->fps);
return TRUE;
}
static void
gst_pngdec_init (GstPngDec * pngdec)
{
pngdec->sinkpad = gst_pad_new_from_template (gst_static_pad_template_get
(&gst_pngdec_sink_pad_template), "sink");
gst_element_add_pad (GST_ELEMENT (pngdec), pngdec->sinkpad);
pngdec->srcpad = gst_pad_new_from_template (gst_static_pad_template_get
(&gst_pngdec_src_pad_template), "src");
gst_element_add_pad (GST_ELEMENT (pngdec), pngdec->srcpad);
gst_pad_set_chain_function (pngdec->sinkpad, gst_pngdec_chain);
gst_pad_set_link_function (pngdec->sinkpad, gst_pngdec_sinklink);
gst_pad_set_getcaps_function (pngdec->srcpad, gst_pngdec_src_getcaps);
pngdec->png = NULL;
pngdec->info = NULL;
pngdec->color_type = -1;
pngdec->width = -1;
pngdec->height = -1;
pngdec->fps = -1;
}
static GstCaps *
gst_pngdec_src_getcaps (GstPad * pad)
{
GstPngDec *pngdec;
GstCaps *caps;
gint i;
GstPadTemplate *templ;
GstCaps *inter;
pngdec = GST_PNGDEC (gst_pad_get_parent (pad));
templ = gst_static_pad_template_get (&gst_pngdec_src_pad_template);
caps = gst_caps_copy (gst_pad_template_get_caps (templ));
if (pngdec->color_type != -1) {
GstCaps *to_inter = NULL;
switch (pngdec->color_type) {
case PNG_COLOR_TYPE_RGB:
to_inter = gst_caps_new_simple ("video/x-raw-rgb",
"bpp", G_TYPE_INT, 24, NULL);
break;
case PNG_COLOR_TYPE_RGB_ALPHA:
to_inter = gst_caps_new_simple ("video/x-raw-rgb",
"bpp", G_TYPE_INT, 32, NULL);
break;
case PNG_COLOR_TYPE_GRAY:
case PNG_COLOR_TYPE_PALETTE:
case PNG_COLOR_TYPE_GRAY_ALPHA:
default:
g_warning ("unsupported colortype");
break;
}
inter = gst_caps_intersect (caps, to_inter);
gst_caps_free (caps);
gst_caps_free (to_inter);
caps = inter;
}
for (i = 0; i < gst_caps_get_size (caps); i++) {
GstStructure *structure = gst_caps_get_structure (caps, i);
g_print ("%d %d\n", pngdec->width, pngdec->height);
if (pngdec->width != -1) {
gst_structure_set (structure, "width", G_TYPE_INT, pngdec->width, NULL);
}
if (pngdec->height != -1) {
gst_structure_set (structure, "height", G_TYPE_INT, pngdec->height, NULL);
}
if (pngdec->fps != -1) {
gst_structure_set (structure,
"framerate", G_TYPE_DOUBLE, pngdec->fps, NULL);
}
}
return caps;
}
static void
user_read_data (png_structp png_ptr, png_bytep data, png_size_t length)
{
GstPngDec *dec;
dec = GST_PNGDEC (png_ptr->io_ptr);
if (GST_BUFFER_SIZE (dec->buffer_in) < dec->offset + length) {
g_warning ("reading past end of buffer");
}
memcpy (data, GST_BUFFER_DATA (dec->buffer_in) + dec->offset, length);
dec->offset += length;
}
static void
gst_pngdec_chain (GstPad * pad, GstData * _data)
{
GstBuffer *buf = GST_BUFFER (_data);
GstPngDec *pngdec;
png_uint_32 width, height;
gint depth, color;
png_bytep *rows, inp;
GstBuffer *out;
gint i;
pngdec = GST_PNGDEC (gst_pad_get_parent (pad));
if (!GST_PAD_IS_USABLE (pngdec->srcpad)) {
gst_buffer_unref (buf);
return;
}
pngdec->buffer_in = buf;
pngdec->offset = 0;
/* initialize png struct stuff */
pngdec->png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
(png_voidp) NULL, user_error_fn, user_warning_fn);
/* FIXME: better error handling */
if (pngdec->png == NULL) {
g_warning ("Failed to initialize png structure");
return;
}
pngdec->info = png_create_info_struct (pngdec->png);
if (pngdec->info == NULL) {
g_warning ("Failed to initialize info structure");
png_destroy_read_struct (&(pngdec->png), (png_infopp) NULL,
(png_infopp) NULL);
return;
}
pngdec->endinfo = png_create_info_struct (pngdec->png);
if (pngdec->endinfo == NULL) {
g_warning ("Failed to initialize endinfo structure");
return;
}
/* non-0 return is from a longjmp inside of libpng */
if (setjmp (pngdec->png->jmpbuf) != 0) {
GST_DEBUG ("returning from longjmp");
png_destroy_read_struct (&pngdec->png, &pngdec->info, &pngdec->endinfo);
return;
}
png_set_read_fn (pngdec->png, pngdec, user_read_data);
png_read_info (pngdec->png, pngdec->info);
png_get_IHDR (pngdec->png, pngdec->info, &width, &height,
&depth, &color, NULL, NULL, NULL);
GST_LOG ("color type: %d\n", pngdec->info->color_type);
if (pngdec->width != width ||
pngdec->height != height ||
pngdec->color_type != pngdec->info->color_type) {
pngdec->width = width;
pngdec->height = height;
pngdec->color_type = pngdec->info->color_type;
if (GST_PAD_LINK_FAILED (gst_pad_renegotiate (pngdec->srcpad))) {
GST_ELEMENT_ERROR (pngdec, CORE, NEGOTIATION, (NULL), (NULL));
return;
}
}
rows = (png_bytep *) g_malloc (sizeof (png_bytep) * height);
out =
gst_pad_alloc_buffer (pngdec->srcpad, GST_BUFFER_OFFSET_NONE,
width * height * 4);
inp = GST_BUFFER_DATA (out);
for (i = 0; i < height; i++) {
rows[i] = inp;
inp += width * 4;
}
png_read_image (pngdec->png, rows);
free (rows);
png_destroy_info_struct (pngdec->png, &pngdec->info);
png_destroy_read_struct (&pngdec->png, &pngdec->info, &pngdec->endinfo);
pngdec->buffer_in = NULL;
gst_buffer_unref (buf);
gst_pad_push (pngdec->srcpad, GST_DATA (out));
}

74
ext/libpng/gstpngdec.h Normal file
View file

@ -0,0 +1,74 @@
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
*
* 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_PNGDEC_H__
#define __GST_PNGDEC_H__
#include <gst/gst.h>
#include <png.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GST_TYPE_PNGDEC (gst_pngdec_get_type())
#define GST_PNGDEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PNGDEC,GstPngDec))
#define GST_PNGDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PNGDEC,GstPngDec))
#define GST_IS_PNGDEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PNGDEC))
#define GST_IS_PNGDEC_CLASS(obj)(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PNGDEC))
typedef struct _GstPngDec GstPngDec;
typedef struct _GstPngDecClass GstPngDecClass;
struct _GstPngDec
{
GstElement element;
GstPad *sinkpad, *srcpad;
GstBuffer *buffer_in;
gint offset;
png_structp png;
png_infop info;
png_infop endinfo;
gint width;
gint height;
gint bpp;
gint color_type;
gdouble fps;
};
struct _GstPngDecClass
{
GstElementClass parent_class;
};
GType gst_pngdec_get_type(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GST_PNGDEC_H__ */