diff options
author | Tim-Philipp Müller <tim@centricular.com> | 2014-11-09 20:53:34 +0000 |
---|---|---|
committer | Tim-Philipp Müller <tim@centricular.com> | 2014-11-09 21:02:15 +0000 |
commit | 6e3518dfd68d775d530bb6c4835b3e0b0e224e16 (patch) | |
tree | 23175db26c7f3f10f062efdd72edd992eb5e22c9 /gst/videoparsers | |
parent | f07de37ad181a6b106b2d0c2003a61ab14e711bc (diff) | |
download | gstreamer-plugins-bad-6e3518dfd68d775d530bb6c4835b3e0b0e224e16.tar.gz |
pngparse: optimise reading of png files
Read PNG data chunk in one go by letting the parser
base class know the size we need, so that it doesn't
drip-feed us small chunks of data (causing a lot of
reallocs and memcpy in the process) until we have
everything.
Improves parsing performance of very large PNG files
(65MB) from ~13 seconds to a couple of millisecs.
https://bugzilla.gnome.org/show_bug.cgi?id=736176
Diffstat (limited to 'gst/videoparsers')
-rw-r--r-- | gst/videoparsers/gstpngparse.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/gst/videoparsers/gstpngparse.c b/gst/videoparsers/gstpngparse.c index efd62a6b2..c4dbe3cf5 100644 --- a/gst/videoparsers/gstpngparse.c +++ b/gst/videoparsers/gstpngparse.c @@ -49,6 +49,7 @@ GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, G_DEFINE_TYPE (GstPngParse, gst_png_parse, GST_TYPE_BASE_PARSE); static gboolean gst_png_parse_start (GstBaseParse * parse); +static gboolean gst_png_parse_event (GstBaseParse * parse, GstEvent * event); static GstFlowReturn gst_png_parse_handle_frame (GstBaseParse * parse, GstBaseParseFrame * frame, gint * skipsize); static GstFlowReturn gst_png_parse_pre_push_frame (GstBaseParse * parse, @@ -72,6 +73,7 @@ gst_png_parse_class_init (GstPngParseClass * klass) /* Override BaseParse vfuncs */ parse_class->start = GST_DEBUG_FUNCPTR (gst_png_parse_start); + parse_class->sink_event = GST_DEBUG_FUNCPTR (gst_png_parse_event); parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_png_parse_handle_frame); parse_class->pre_push_frame = GST_DEBUG_FUNCPTR (gst_png_parse_pre_push_frame); @@ -100,6 +102,24 @@ gst_png_parse_start (GstBaseParse * parse) return TRUE; } +static gboolean +gst_png_parse_event (GstBaseParse * parse, GstEvent * event) +{ + gboolean res; + + res = GST_BASE_PARSE_CLASS (parent_class)->sink_event (parse, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + /* the start code and at least 2 empty frames (IHDR and IEND) */ + gst_base_parse_set_min_frame_size (parse, 8 + 12 + 12); + break; + default: + break; + } + + return res; +} static GstFlowReturn gst_png_parse_handle_frame (GstBaseParse * parse, @@ -155,18 +175,27 @@ gst_png_parse_handle_frame (GstBaseParse * parse, if (!gst_byte_reader_get_uint32_le (&reader, &code)) goto beach; + GST_INFO_OBJECT (parse, "%" GST_FOURCC_FORMAT " chunk, %u bytes", + GST_FOURCC_ARGS (code), length); + if (code == GST_MAKE_FOURCC ('I', 'H', 'D', 'R')) { if (!gst_byte_reader_get_uint32_be (&reader, &width)) goto beach; if (!gst_byte_reader_get_uint32_be (&reader, &height)) goto beach; length -= 8; + } else if (code == GST_MAKE_FOURCC ('I', 'D', 'A', 'T')) { + gst_base_parse_set_min_frame_size (parse, + gst_byte_reader_get_pos (&reader) + 4 + length + 12); } if (!gst_byte_reader_skip (&reader, length + 4)) goto beach; if (code == GST_MAKE_FOURCC ('I', 'E', 'N', 'D')) { + /* the start code and at least 2 empty frames (IHDR and IEND) */ + gst_base_parse_set_min_frame_size (parse, 8 + 12 + 12); + if (pngparse->width != width || pngparse->height != height) { GstCaps *caps, *sink_caps; |