summaryrefslogtreecommitdiff
path: root/ext/libpng
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2012-05-28 15:22:26 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2012-05-28 15:22:55 +0200
commit5ba30e61116155c781c59176d7db3a702c4b43b2 (patch)
tree7a07e7c7a4d7dab63a8f3e4dd9d362bb9606ab01 /ext/libpng
parent982c1b479f5f29415e6431d324c85a5dd60ceaa5 (diff)
png: Port to 0.11 again
Diffstat (limited to 'ext/libpng')
-rw-r--r--ext/libpng/gstpngdec.c136
-rw-r--r--ext/libpng/gstpngdec.h5
-rw-r--r--ext/libpng/gstpngenc.c98
-rw-r--r--ext/libpng/gstpngenc.h1
4 files changed, 147 insertions, 93 deletions
diff --git a/ext/libpng/gstpngdec.c b/ext/libpng/gstpngdec.c
index 429b585c1..e2c778c06 100644
--- a/ext/libpng/gstpngdec.c
+++ b/ext/libpng/gstpngdec.c
@@ -30,6 +30,8 @@
#include <stdlib.h>
#include <string.h>
#include <gst/video/video.h>
+#include <gst/video/gstvideometa.h>
+#include <gst/video/gstvideopool.h>
#include <gst/gst-i18n-plugin.h>
GST_DEBUG_CATEGORY_STATIC (pngdec_debug);
@@ -46,17 +48,18 @@ static gboolean gst_pngdec_set_format (GstVideoDecoder * Decoder,
GstVideoCodecState * state);
static GstFlowReturn gst_pngdec_handle_frame (GstVideoDecoder * decoder,
GstVideoCodecFrame * frame);
+static gboolean gst_pngdec_decide_allocation (GstVideoDecoder * decoder,
+ GstQuery * query);
-GST_BOILERPLATE (GstPngDec, gst_pngdec, GstVideoDecoder,
- GST_TYPE_VIDEO_DECODER);
+#define parent_class gst_pngdec_parent_class
+G_DEFINE_TYPE (GstPngDec, gst_pngdec, GST_TYPE_VIDEO_DECODER);
static GstStaticPadTemplate gst_pngdec_src_pad_template =
- GST_STATIC_PAD_TEMPLATE ("src",
+GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_RGB ";"
- GST_VIDEO_CAPS_ARGB_64 ";"
- GST_VIDEO_CAPS_GRAY8 ";" GST_VIDEO_CAPS_GRAY16 ("BIG_ENDIAN"))
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
+ ("{ RGBA, RGB, ARGB64, GRAY8, GRAY16_BE }"))
);
static GstStaticPadTemplate gst_pngdec_sink_pad_template =
@@ -67,37 +70,32 @@ GST_STATIC_PAD_TEMPLATE ("sink",
);
static void
-gst_pngdec_base_init (gpointer g_class)
+gst_pngdec_class_init (GstPngDecClass * klass)
{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+ GstElementClass *element_class = (GstElementClass *) klass;
+ GstVideoDecoderClass *vdec_class = (GstVideoDecoderClass *) klass;
- gst_element_class_add_static_pad_template (element_class,
- &gst_pngdec_src_pad_template);
- gst_element_class_add_static_pad_template (element_class,
- &gst_pngdec_sink_pad_template);
+ 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_simple (element_class, "PNG image decoder",
"Codec/Decoder/Image",
"Decode a png video frame to a raw image",
"Wim Taymans <wim@fluendo.com>");
-}
-
-static void
-gst_pngdec_class_init (GstPngDecClass * klass)
-{
- GstVideoDecoderClass *vdec_class = (GstVideoDecoderClass *) klass;
vdec_class->start = gst_pngdec_start;
vdec_class->reset = gst_pngdec_reset;
vdec_class->set_format = gst_pngdec_set_format;
vdec_class->handle_frame = gst_pngdec_handle_frame;
+ vdec_class->decide_allocation = gst_pngdec_decide_allocation;
GST_DEBUG_CATEGORY_INIT (pngdec_debug, "pngdec", 0, "PNG image decoder");
}
static void
-gst_pngdec_init (GstPngDec * pngdec, GstPngDecClass * klass)
+gst_pngdec_init (GstPngDec * pngdec)
{
- pngdec->buffer_out = NULL;
pngdec->png = NULL;
pngdec->info = NULL;
pngdec->endinfo = NULL;
@@ -124,8 +122,6 @@ user_info_callback (png_structp png_ptr, png_infop info)
{
GstPngDec *pngdec = NULL;
GstFlowReturn ret = GST_FLOW_OK;
- size_t buffer_size;
- guint height;
GST_LOG ("info ready");
@@ -136,24 +132,12 @@ user_info_callback (png_structp png_ptr, png_infop info)
goto beach;
}
- height = GST_VIDEO_INFO_HEIGHT (&pngdec->output_state->info);
-
/* Allocate output buffer */
- pngdec->rowbytes = png_get_rowbytes (pngdec->png, pngdec->info);
- GST_DEBUG ("png told us each row takes %d bytes", pngdec->rowbytes);
- if (pngdec->rowbytes > (G_MAXUINT32 - 3)
- || height > G_MAXUINT32 / pngdec->rowbytes) {
- ret = GST_FLOW_ERROR;
- goto beach;
- }
- pngdec->rowbytes = GST_ROUND_UP_4 (pngdec->rowbytes);
- buffer_size = height * pngdec->rowbytes;
-
- GST_DEBUG ("Allocating a buffer of %d bytes", buffer_size);
-
- g_assert (pngdec->buffer_out == NULL);
- pngdec->buffer_out = pngdec->current_frame->output_buffer =
- gst_buffer_new_and_alloc (buffer_size);
+ ret =
+ gst_video_decoder_alloc_output_frame (GST_VIDEO_DECODER (pngdec),
+ pngdec->current_frame);
+ if (G_UNLIKELY (ret != GST_FLOW_OK))
+ GST_DEBUG_OBJECT (pngdec, "failed to acquire buffer");
beach:
pngdec->ret = ret;
@@ -185,13 +169,26 @@ user_endrow_callback (png_structp png_ptr, png_bytep new_row,
/* If buffer_out doesn't exist, it means buffer_alloc failed, which
* will already have set the return code */
- if (GST_IS_BUFFER (pngdec->buffer_out)) {
- size_t offset = row_num * pngdec->rowbytes;
+ if (GST_IS_BUFFER (pngdec->current_frame->output_buffer)) {
+ GstVideoFrame frame;
+ GstBuffer *buffer = pngdec->current_frame->output_buffer;
+ size_t offset;
+ gint width;
+ guint8 *data;
+
+ if (!gst_video_frame_map (&frame, &pngdec->output_state->info, buffer,
+ GST_MAP_WRITE)) {
+ pngdec->ret = GST_FLOW_ERROR;
+ return;
+ }
+ data = GST_VIDEO_FRAME_COMP_DATA (&frame, 0);
+ offset = row_num * GST_VIDEO_FRAME_COMP_STRIDE (&frame, 0);
GST_LOG ("got row %u, copying in buffer %p at offset %" G_GSIZE_FORMAT,
- (guint) row_num, pngdec->buffer_out, offset);
- memcpy (GST_BUFFER_DATA (pngdec->buffer_out) + offset, new_row,
- pngdec->rowbytes);
+ (guint) row_num, pngdec->current_frame->output_buffer, offset);
+ width = GST_ROUND_UP_4 (png_get_rowbytes (pngdec->png, pngdec->info));
+ memcpy (data + offset, new_row, width);
+ gst_video_frame_unmap (&frame);
pngdec->ret = GST_FLOW_OK;
}
}
@@ -205,14 +202,16 @@ user_end_callback (png_structp png_ptr, png_infop info)
GST_LOG_OBJECT (pngdec, "and we are done reading this image");
- if (!pngdec->buffer_out)
+ if (!pngdec->current_frame->output_buffer)
return;
+ gst_buffer_unmap (pngdec->current_frame->input_buffer,
+ &pngdec->current_frame_map);
+
pngdec->ret =
gst_video_decoder_finish_frame (GST_VIDEO_DECODER (pngdec),
pngdec->current_frame);
- pngdec->buffer_out = NULL;
pngdec->image_ready = TRUE;
}
@@ -344,7 +343,7 @@ gst_pngdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
GstFlowReturn ret = GST_FLOW_OK;
GST_LOG_OBJECT (pngdec, "Got buffer, size=%u",
- GST_BUFFER_SIZE (frame->input_buffer));
+ gst_buffer_get_size (frame->input_buffer));
/* Let libpng come back here on error */
if (setjmp (png_jmpbuf (pngdec->png))) {
@@ -356,9 +355,15 @@ gst_pngdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
pngdec->current_frame = frame;
/* Progressive loading of the PNG image */
+ if (!gst_buffer_map (frame->input_buffer, &pngdec->current_frame_map,
+ GST_MAP_READ)) {
+ GST_WARNING_OBJECT (pngdec, "Failed to map input buffer");
+ ret = GST_FLOW_ERROR;
+ goto beach;
+ }
+
png_process_data (pngdec->png, pngdec->info,
- GST_BUFFER_DATA (frame->input_buffer),
- GST_BUFFER_SIZE (frame->input_buffer));
+ pngdec->current_frame_map.data, pngdec->current_frame_map.size);
if (pngdec->image_ready) {
if (1) {
@@ -369,9 +374,13 @@ gst_pngdec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame)
user_info_callback, user_endrow_callback, user_end_callback);
} else {
GST_LOG_OBJECT (pngdec, "sending EOS");
- pngdec->ret = GST_FLOW_UNEXPECTED;
+ pngdec->ret = GST_FLOW_EOS;
}
pngdec->image_ready = FALSE;
+ } else {
+ /* An error happened and we have to unmap */
+ gst_buffer_unmap (pngdec->current_frame->input_buffer,
+ &pngdec->current_frame_map);
}
ret = pngdec->ret;
@@ -380,6 +389,31 @@ beach:
return ret;
}
+static gboolean
+gst_pngdec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query)
+{
+ GstBufferPool *pool;
+ GstStructure *config;
+
+ if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (bdec, query))
+ return FALSE;
+
+ g_assert (gst_query_get_n_allocation_pools (query) > 0);
+ gst_query_parse_nth_allocation_pool (query, 0, &pool, NULL, NULL, NULL);
+ g_assert (pool != NULL);
+
+ config = gst_buffer_pool_get_config (pool);
+ if (gst_query_has_allocation_meta (query, GST_VIDEO_META_API_TYPE)) {
+ gst_buffer_pool_config_add_option (config,
+ GST_BUFFER_POOL_OPTION_VIDEO_META);
+ }
+ gst_buffer_pool_set_config (pool, config);
+ gst_object_unref (pool);
+
+ return TRUE;
+}
+
+
/* Clean up the libpng structures */
static gboolean
gst_pngdec_reset (GstVideoDecoder * decoder, gboolean hard)
@@ -472,8 +506,6 @@ gst_pngdec_stop (GstVideoDecoder * decoder)
}
pngdec->color_type = -1;
- pngdec->rowbytes = 0;
- pngdec->buffer_out = NULL;
return TRUE;
}
diff --git a/ext/libpng/gstpngdec.h b/ext/libpng/gstpngdec.h
index f5639d329..69a4ff67c 100644
--- a/ext/libpng/gstpngdec.h
+++ b/ext/libpng/gstpngdec.h
@@ -44,14 +44,11 @@ struct _GstPngDec
GstVideoCodecState *input_state;
GstVideoCodecState *output_state;
+ GstMapInfo current_frame_map;
GstVideoCodecFrame *current_frame;
GstFlowReturn ret;
- /* Progressive */
- GstBuffer *buffer_out;
- png_uint_32 rowbytes;
-
png_structp png;
png_infop info;
png_infop endinfo;
diff --git a/ext/libpng/gstpngenc.c b/ext/libpng/gstpngenc.c
index 13fee1ed8..f8dcff4dd 100644
--- a/ext/libpng/gstpngenc.c
+++ b/ext/libpng/gstpngenc.c
@@ -31,6 +31,7 @@
#include <gst/gst.h>
#include "gstpngenc.h"
#include <gst/video/video.h>
+#include <gst/video/gstvideometa.h>
#include <zlib.h>
GST_DEBUG_CATEGORY_STATIC (pngenc_debug);
@@ -43,7 +44,7 @@ enum
LAST_SIGNAL
};
-#define DEFAULT_SNAPSHOT TRUE
+#define DEFAULT_SNAPSHOT FALSE
#define DEFAULT_COMPRESSION_LEVEL 6
enum
@@ -63,15 +64,14 @@ GST_STATIC_PAD_TEMPLATE ("src",
);
static GstStaticPadTemplate pngenc_sink_template =
- GST_STATIC_PAD_TEMPLATE ("sink",
+GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_RGB ";"
- GST_VIDEO_CAPS_GRAY8 ";" GST_VIDEO_CAPS_GRAY16 ("BIG_ENDIAN"))
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("{ RGBA, RGB, GRAY8, GRAY16_BE }"))
);
-GST_BOILERPLATE (GstPngEnc, gst_pngenc, GstVideoEncoder,
- GST_TYPE_VIDEO_ENCODER);
+#define parent_class gst_pngenc_parent_class
+G_DEFINE_TYPE (GstPngEnc, gst_pngenc, GST_TYPE_VIDEO_ENCODER);
static void gst_pngenc_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -82,6 +82,8 @@ static GstFlowReturn gst_pngenc_handle_frame (GstVideoEncoder * encoder,
GstVideoCodecFrame * frame);
static gboolean gst_pngenc_set_format (GstVideoEncoder * encoder,
GstVideoCodecState * state);
+static gboolean gst_pngenc_propose_allocation (GstVideoEncoder * encoder,
+ GstQuery * query);
static void
user_error_fn (png_structp png_ptr, png_const_charp error_msg)
@@ -96,27 +98,14 @@ user_warning_fn (png_structp png_ptr, png_const_charp warning_msg)
}
static void
-gst_pngenc_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_static_pad_template
- (element_class, &pngenc_sink_template);
- gst_element_class_add_static_pad_template
- (element_class, &pngenc_src_template);
- gst_element_class_set_details_simple (element_class, "PNG image encoder",
- "Codec/Encoder/Image",
- "Encode a video frame to a .png image",
- "Jeremy SIMON <jsimon13@yahoo.fr>");
-}
-
-static void
gst_pngenc_class_init (GstPngEncClass * klass)
{
GObjectClass *gobject_class;
+ GstElementClass *element_class;
GstVideoEncoderClass *venc_class;
gobject_class = (GObjectClass *) klass;
+ element_class = (GstElementClass *) klass;
venc_class = (GstVideoEncoderClass *) klass;
parent_class = g_type_class_peek_parent (klass);
@@ -136,8 +125,18 @@ gst_pngenc_class_init (GstPngEncClass * klass)
DEFAULT_COMPRESSION_LEVEL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ gst_element_class_add_pad_template
+ (element_class, gst_static_pad_template_get (&pngenc_sink_template));
+ gst_element_class_add_pad_template
+ (element_class, gst_static_pad_template_get (&pngenc_src_template));
+ gst_element_class_set_details_simple (element_class, "PNG image encoder",
+ "Codec/Encoder/Image",
+ "Encode a video frame to a .png image",
+ "Jeremy SIMON <jsimon13@yahoo.fr>");
+
venc_class->set_format = gst_pngenc_set_format;
venc_class->handle_frame = gst_pngenc_handle_frame;
+ venc_class->propose_allocation = gst_pngenc_propose_allocation;
GST_DEBUG_CATEGORY_INIT (pngenc_debug, "pngenc", 0, "PNG image encoder");
}
@@ -185,7 +184,7 @@ gst_pngenc_set_format (GstVideoEncoder * encoder, GstVideoCodecState * state)
output_state =
gst_video_encoder_set_output_state (encoder,
- gst_caps_new_simple ("image/png", NULL), state);
+ gst_caps_new_empty_simple ("image/png"), state);
gst_video_codec_state_unref (output_state);
done:
@@ -194,7 +193,7 @@ done:
}
static void
-gst_pngenc_init (GstPngEnc * pngenc, GstPngEncClass * g_class)
+gst_pngenc_init (GstPngEnc * pngenc)
{
/* init settings */
pngenc->png_struct_ptr = NULL;
@@ -213,19 +212,34 @@ static void
user_write_data (png_structp png_ptr, png_bytep data, png_uint_32 length)
{
GstPngEnc *pngenc;
+ GstMemory *mem;
+ GstMapInfo minfo;
pngenc = (GstPngEnc *) png_get_io_ptr (png_ptr);
- if (pngenc->written + length >= GST_BUFFER_SIZE (pngenc->buffer_out)) {
- GST_ERROR_OBJECT (pngenc, "output buffer bigger than the input buffer!?");
- png_error (png_ptr, "output buffer bigger than the input buffer!?");
+ mem = gst_allocator_alloc (NULL, length, NULL);
+ if (!mem) {
+ GST_ERROR_OBJECT (pngenc, "Failed to allocate memory");
+ png_error (png_ptr, "Failed to allocate memory");
/* never reached */
return;
}
- memcpy (GST_BUFFER_DATA (pngenc->buffer_out) + pngenc->written, data, length);
- pngenc->written += length;
+ if (!gst_memory_map (mem, &minfo, GST_MAP_WRITE)) {
+ GST_ERROR_OBJECT (pngenc, "Failed to map memory");
+ gst_memory_unref (mem);
+
+ png_error (png_ptr, "Failed to map memory");
+
+ /* never reached */
+ return;
+ }
+
+ memcpy (minfo.data, data, length);
+ gst_memory_unmap (mem, &minfo);
+
+ gst_buffer_append_memory (pngenc->buffer_out, mem);
}
static GstFlowReturn
@@ -236,6 +250,7 @@ gst_pngenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
png_byte **row_pointers;
GstFlowReturn ret = GST_FLOW_OK;
GstVideoInfo *info;
+ GstVideoFrame vframe;
pngenc = GST_PNGENC (encoder);
info = &pngenc->input_state->info;
@@ -273,17 +288,21 @@ gst_pngenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
(png_rw_ptr) user_write_data, user_flush_data);
row_pointers = g_new (png_byte *, GST_VIDEO_INFO_HEIGHT (info));
+ if (!gst_video_frame_map (&vframe, &pngenc->input_state->info,
+ frame->input_buffer, GST_MAP_READ)) {
+ GST_ELEMENT_ERROR (pngenc, STREAM, FORMAT, (NULL),
+ ("Failed to map video frame, caps problem?"));
+ ret = GST_FLOW_ERROR;
+ goto done;
+ }
for (row_index = 0; row_index < GST_VIDEO_INFO_HEIGHT (info); row_index++) {
- row_pointers[row_index] = GST_BUFFER_DATA (frame->input_buffer) +
- (row_index * GST_VIDEO_INFO_COMP_STRIDE (info, 0));
+ row_pointers[row_index] = GST_VIDEO_FRAME_COMP_DATA (&vframe, 0) +
+ (row_index * GST_VIDEO_FRAME_COMP_STRIDE (&vframe, 0));
}
/* allocate the output buffer */
- pngenc->buffer_out =
- gst_buffer_new_and_alloc (GST_VIDEO_INFO_HEIGHT (info) *
- GST_VIDEO_INFO_COMP_STRIDE (info, 0));
- pngenc->written = 0;
+ pngenc->buffer_out = gst_buffer_new ();
png_write_info (pngenc->png_struct_ptr, pngenc->png_info_ptr);
png_write_image (pngenc->png_struct_ptr, row_pointers);
@@ -295,7 +314,6 @@ gst_pngenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
png_destroy_write_struct (&pngenc->png_struct_ptr, (png_infopp) NULL);
/* Set final size and store */
- GST_BUFFER_SIZE (pngenc->buffer_out) = pngenc->written;
frame->output_buffer = pngenc->buffer_out;
pngenc->buffer_out = NULL;
@@ -304,7 +322,7 @@ gst_pngenc_handle_frame (GstVideoEncoder * encoder, GstVideoCodecFrame * frame)
goto done;
if (pngenc->snapshot)
- ret = GST_FLOW_UNEXPECTED;
+ ret = GST_FLOW_EOS;
done:
GST_DEBUG_OBJECT (pngenc, "END, ret:%d", ret);
@@ -336,6 +354,14 @@ longjmp_fail:
}
}
+static gboolean
+gst_pngenc_propose_allocation (GstVideoEncoder * encoder, GstQuery * query)
+{
+ gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE);
+
+ return GST_VIDEO_ENCODER_CLASS (parent_class)->propose_allocation (encoder,
+ query);
+}
static void
gst_pngenc_get_property (GObject * object,
diff --git a/ext/libpng/gstpngenc.h b/ext/libpng/gstpngenc.h
index b8150d401..87bee9281 100644
--- a/ext/libpng/gstpngenc.h
+++ b/ext/libpng/gstpngenc.h
@@ -47,7 +47,6 @@ struct _GstPngEnc
GstVideoCodecState *input_state;
GstBuffer *buffer_out;
- guint written;
png_structp png_struct_ptr;
png_infop png_info_ptr;