mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
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
This commit is contained in:
parent
f07de37ad1
commit
6e3518dfd6
1 changed files with 29 additions and 0 deletions
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue