summaryrefslogtreecommitdiff
path: root/gst/videoparsers
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim@centricular.com>2014-11-09 20:53:34 +0000
committerTim-Philipp Müller <tim@centricular.com>2014-11-09 21:02:15 +0000
commit6e3518dfd68d775d530bb6c4835b3e0b0e224e16 (patch)
tree23175db26c7f3f10f062efdd72edd992eb5e22c9 /gst/videoparsers
parentf07de37ad181a6b106b2d0c2003a61ab14e711bc (diff)
downloadgstreamer-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.c29
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;