mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +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);
|
G_DEFINE_TYPE (GstPngParse, gst_png_parse, GST_TYPE_BASE_PARSE);
|
||||||
|
|
||||||
static gboolean gst_png_parse_start (GstBaseParse * 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,
|
static GstFlowReturn gst_png_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, gint * skipsize);
|
GstBaseParseFrame * frame, gint * skipsize);
|
||||||
static GstFlowReturn gst_png_parse_pre_push_frame (GstBaseParse * parse,
|
static GstFlowReturn gst_png_parse_pre_push_frame (GstBaseParse * parse,
|
||||||
|
@ -72,6 +73,7 @@ gst_png_parse_class_init (GstPngParseClass * klass)
|
||||||
|
|
||||||
/* Override BaseParse vfuncs */
|
/* Override BaseParse vfuncs */
|
||||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_png_parse_start);
|
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->handle_frame = GST_DEBUG_FUNCPTR (gst_png_parse_handle_frame);
|
||||||
parse_class->pre_push_frame =
|
parse_class->pre_push_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_png_parse_pre_push_frame);
|
GST_DEBUG_FUNCPTR (gst_png_parse_pre_push_frame);
|
||||||
|
@ -100,6 +102,24 @@ gst_png_parse_start (GstBaseParse * parse)
|
||||||
return TRUE;
|
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
|
static GstFlowReturn
|
||||||
gst_png_parse_handle_frame (GstBaseParse * parse,
|
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))
|
if (!gst_byte_reader_get_uint32_le (&reader, &code))
|
||||||
goto beach;
|
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 (code == GST_MAKE_FOURCC ('I', 'H', 'D', 'R')) {
|
||||||
if (!gst_byte_reader_get_uint32_be (&reader, &width))
|
if (!gst_byte_reader_get_uint32_be (&reader, &width))
|
||||||
goto beach;
|
goto beach;
|
||||||
if (!gst_byte_reader_get_uint32_be (&reader, &height))
|
if (!gst_byte_reader_get_uint32_be (&reader, &height))
|
||||||
goto beach;
|
goto beach;
|
||||||
length -= 8;
|
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))
|
if (!gst_byte_reader_skip (&reader, length + 4))
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
if (code == GST_MAKE_FOURCC ('I', 'E', 'N', 'D')) {
|
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) {
|
if (pngparse->width != width || pngparse->height != height) {
|
||||||
GstCaps *caps, *sink_caps;
|
GstCaps *caps, *sink_caps;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue