diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-05-28 15:22:26 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-05-28 15:22:55 +0200 |
commit | 5ba30e61116155c781c59176d7db3a702c4b43b2 (patch) | |
tree | 7a07e7c7a4d7dab63a8f3e4dd9d362bb9606ab01 /ext/libpng | |
parent | 982c1b479f5f29415e6431d324c85a5dd60ceaa5 (diff) |
png: Port to 0.11 again
Diffstat (limited to 'ext/libpng')
-rw-r--r-- | ext/libpng/gstpngdec.c | 136 | ||||
-rw-r--r-- | ext/libpng/gstpngdec.h | 5 | ||||
-rw-r--r-- | ext/libpng/gstpngenc.c | 98 | ||||
-rw-r--r-- | ext/libpng/gstpngenc.h | 1 |
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; |