From 6e3518dfd68d775d530bb6c4835b3e0b0e224e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 9 Nov 2014 20:53:34 +0000 Subject: [PATCH] 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 --- gst/videoparsers/gstpngparse.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/gst/videoparsers/gstpngparse.c b/gst/videoparsers/gstpngparse.c index efd62a6b2f..c4dbe3cf54 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;