summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim.muller@collabora.co.uk>2009-11-09 11:40:25 +0000
committerTim-Philipp Müller <tim.muller@collabora.co.uk>2009-11-09 15:18:58 +0000
commit26e7fe27d7b4fb8faa1c88e13aca8cc799ff1dc1 (patch)
treedbc28b4007524360deb3779b64d65ce0f4e3231a
parent2270d3359ad6df38d270b0e63d825bddc800a68e (diff)
jpegdec: only allocate as much temporary memory as needed for indirect decoding
When we can't decode directly into the output buffer, make our temp buffers only as big as needed instead of allocating for the worst case scenario (well, we still alloc more than strictly needed for some cases, but significantly less than before).
-rw-r--r--ext/jpeg/gstjpegdec.c41
-rw-r--r--ext/jpeg/gstjpegdec.h2
2 files changed, 28 insertions, 15 deletions
diff --git a/ext/jpeg/gstjpegdec.c b/ext/jpeg/gstjpegdec.c
index 07128d418..ef94a5abc 100644
--- a/ext/jpeg/gstjpegdec.c
+++ b/ext/jpeg/gstjpegdec.c
@@ -682,6 +682,31 @@ hresamplecpy1 (guint8 * dest, const guint8 * src, guint len)
}
}
+static inline gboolean
+gst_jpeg_dec_ensure_buffers (GstJpegDec * dec, guint maxrowbytes)
+{
+ gint i;
+
+ if (G_LIKELY (dec->idr_width_allocated == maxrowbytes))
+ return TRUE;
+
+ /* FIXME: maybe just alloc one or three blocks altogether? */
+ for (i = 0; i < 16; i++) {
+ dec->idr_y[i] = g_try_realloc (dec->idr_y[i], maxrowbytes);
+ dec->idr_u[i] = g_try_realloc (dec->idr_u[i], maxrowbytes);
+ dec->idr_v[i] = g_try_realloc (dec->idr_v[i], maxrowbytes);
+
+ if (G_UNLIKELY (!dec->idr_y[i] || !dec->idr_u[i] || !dec->idr_v[i])) {
+ GST_WARNING_OBJECT (dec, "out of memory, i=%d, bytes=%u", i, maxrowbytes);
+ return FALSE;
+ }
+ }
+
+ dec->idr_width_allocated = maxrowbytes;
+ GST_LOG_OBJECT (dec, "allocated temp memory, %u bytes/row", maxrowbytes);
+ return TRUE;
+}
+
static void
gst_jpeg_dec_decode_indirect (GstJpegDec * dec, guchar * base[3],
guchar * last[3], guint width, guint height, gint r_v, gint r_h)
@@ -694,20 +719,8 @@ gst_jpeg_dec_decode_indirect (GstJpegDec * dec, guchar * base[3],
GST_DEBUG_OBJECT (dec,
"unadvantageous width or r_h, taking slow route involving memcpy");
- if (G_UNLIKELY (!dec->idr_allocated)) {
- gboolean res = TRUE;
-
- for (i = 0; ((i < 16) && res); i++) {
- res &= ((dec->idr_y[i] = g_try_malloc (MAX_WIDTH)) != NULL);
- res &= ((dec->idr_u[i] = g_try_malloc (MAX_WIDTH)) != NULL);
- res &= ((dec->idr_v[i] = g_try_malloc (MAX_WIDTH)) != NULL);
- }
- if (!res) {
- GST_WARNING_OBJECT (dec, "out of memory");
- return;
- }
- dec->idr_allocated = TRUE;
- }
+ if (G_UNLIKELY (!gst_jpeg_dec_ensure_buffers (dec, GST_ROUND_UP_32 (width))))
+ return;
memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
diff --git a/ext/jpeg/gstjpegdec.h b/ext/jpeg/gstjpegdec.h
index 0be995195..68affa82e 100644
--- a/ext/jpeg/gstjpegdec.h
+++ b/ext/jpeg/gstjpegdec.h
@@ -108,7 +108,7 @@ struct _GstJpegDec {
struct GstJpegDecSourceMgr jsrc;
/* arrays for indirect decoding */
- gboolean idr_allocated;
+ gboolean idr_width_allocated;
guchar *idr_y[16],*idr_u[16],*idr_v[16];
};