jpegdec: only allocate as much temporary memory as needed for indirect decoding
authorTim-Philipp Müller <tim.muller@collabora.co.uk>
Mon, 9 Nov 2009 11:40:25 +0000 (11:40 +0000)
committerTim-Philipp Müller <tim.muller@collabora.co.uk>
Mon, 9 Nov 2009 15:18:58 +0000 (15:18 +0000)
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).

ext/jpeg/gstjpegdec.c
ext/jpeg/gstjpegdec.h

index 07128d4..ef94a5a 100644 (file)
@@ -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));
index 0be9951..68affa8 100644 (file)
@@ -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];
 };