summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Kost <ensonic@users.sf.net>2009-11-03 17:35:15 +0200
committerStefan Kost <ensonic@users.sf.net>2009-11-03 17:49:24 +0200
commite3e910e971141c6ee88c0dbb802469bf81855e12 (patch)
tree0ffbb05ede8ffe283e5cba7091f22dabdc2bbf05
parent65a1db99eb559064a5628e7dfbd9a32e4b56e08b (diff)
jpegdec: don't allocate big arrays on the stack
Add the arrays to the instance data and allocate on first use.
-rw-r--r--ext/jpeg/gstjpegdec.c41
-rw-r--r--ext/jpeg/gstjpegdec.h4
2 files changed, 31 insertions, 14 deletions
diff --git a/ext/jpeg/gstjpegdec.c b/ext/jpeg/gstjpegdec.c
index f481e0e65..07128d418 100644
--- a/ext/jpeg/gstjpegdec.c
+++ b/ext/jpeg/gstjpegdec.c
@@ -148,12 +148,19 @@ static void
gst_jpeg_dec_finalize (GObject * object)
{
GstJpegDec *dec = GST_JPEG_DEC (object);
+ gint i;
jpeg_destroy_decompress (&dec->cinfo);
if (dec->tempbuf)
gst_buffer_unref (dec->tempbuf);
+ for (i = 0; i < 16; i++) {
+ g_free (dec->idr_y[i]);
+ g_free (dec->idr_u[i]);
+ g_free (dec->idr_v[i]);
+ }
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -679,20 +686,7 @@ 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)
{
- /* FIXME: these are too large now that MAX_WIDTH is 64k! Allocating 3MB on
- * the stack is not very nice... */
- guchar y[16][MAX_WIDTH];
- guchar u[16][MAX_WIDTH];
- guchar v[16][MAX_WIDTH];
- guchar *y_rows[16] = { y[0], y[1], y[2], y[3], y[4], y[5], y[6], y[7],
- y[8], y[9], y[10], y[11], y[12], y[13], y[14], y[15]
- };
- guchar *u_rows[16] = { u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7],
- u[8], u[9], u[10], u[11], u[12], u[13], u[14], u[15]
- };
- guchar *v_rows[16] = { v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7],
- v[8], v[9], v[10], v[11], v[12], v[13], v[14], v[15]
- };
+ guchar *y_rows[16], *u_rows[16], *v_rows[16];
guchar **scanarray[3] = { y_rows, u_rows, v_rows };
gint i, j, k;
gint lines;
@@ -700,6 +694,25 @@ 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;
+ }
+
+ memcpy (y_rows, dec->idr_y, 16 * sizeof (gpointer));
+ memcpy (u_rows, dec->idr_u, 16 * sizeof (gpointer));
+ memcpy (v_rows, dec->idr_v, 16 * sizeof (gpointer));
+
for (i = 0; i < height; i += r_v * DCTSIZE) {
lines = jpeg_read_raw_data (&dec->cinfo, scanarray, r_v * DCTSIZE);
if (G_LIKELY (lines > 0)) {
diff --git a/ext/jpeg/gstjpegdec.h b/ext/jpeg/gstjpegdec.h
index aa23c6137..0be995195 100644
--- a/ext/jpeg/gstjpegdec.h
+++ b/ext/jpeg/gstjpegdec.h
@@ -106,6 +106,10 @@ struct _GstJpegDec {
struct jpeg_decompress_struct cinfo;
struct GstJpegDecErrorMgr jerr;
struct GstJpegDecSourceMgr jsrc;
+
+ /* arrays for indirect decoding */
+ gboolean idr_allocated;
+ guchar *idr_y[16],*idr_u[16],*idr_v[16];
};
struct _GstJpegDecClass {