[1.5] Apply private patch from Alex Macfarlane Smith

This gets rids of a lot memory leaks when used on device with low memory
This commit is contained in:
Mathieu Malaterre 2012-05-29 14:52:45 +00:00
parent 835bf5357f
commit 6c5a066b20
4 changed files with 110 additions and 22 deletions

View File

@ -558,7 +558,17 @@ static void j2k_read_siz(opj_j2k_t *j2k) {
#endif /* USE_JPWL */ #endif /* USE_JPWL */
cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t)); cp->tcps = (opj_tcp_t*) opj_calloc(cp->tw * cp->th, sizeof(opj_tcp_t));
if (cp->tcps == NULL)
{
opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n");
return;
}
cp->tileno = (int*) opj_malloc(cp->tw * cp->th * sizeof(int)); cp->tileno = (int*) opj_malloc(cp->tw * cp->th * sizeof(int));
if (cp->tileno == NULL)
{
opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n");
return;
}
cp->tileno_size = 0; cp->tileno_size = 0;
#ifdef USE_JPWL #ifdef USE_JPWL
@ -1737,6 +1747,14 @@ void j2k_destroy_decompress(opj_j2k_t *j2k) {
opj_free(j2k->tile_len); opj_free(j2k->tile_len);
} }
if(j2k->tile_data != NULL) { if(j2k->tile_data != NULL) {
if(j2k->cp != NULL) {
for (i = 0; i < j2k->cp->tileno_size; i++) {
int tileno = j2k->cp->tileno[i];
opj_free(j2k->tile_data[tileno]);
j2k->tile_data[tileno] = NULL;
}
}
opj_free(j2k->tile_data); opj_free(j2k->tile_data);
} }
if(j2k->default_tcp != NULL) { if(j2k->default_tcp != NULL) {
@ -1877,7 +1895,10 @@ opj_image_t* j2k_decode(opj_j2k_t *j2k, opj_cio_t *cio, opj_codestream_info_t *c
(*e->handler)(j2k); (*e->handler)(j2k);
} }
if (j2k->state & J2K_STATE_ERR) if (j2k->state & J2K_STATE_ERR)
{
opj_image_destroy(image);
return NULL; return NULL;
}
if (j2k->state == J2K_STATE_MT) { if (j2k->state == J2K_STATE_MT) {
break; break;

View File

@ -1577,6 +1577,7 @@ void t1_decode_cblks(
opj_free(cblk->segs); opj_free(cblk->segs);
} /* cblkno */ } /* cblkno */
opj_free(precinct->cblks.dec); opj_free(precinct->cblks.dec);
precinct->cblks.dec = NULL;
} /* precno */ } /* precno */
} /* bandno */ } /* bandno */
} /* resno */ } /* resno */

View File

@ -64,7 +64,7 @@ static int t2_encode_packet(opj_tcd_tile_t *tile, opj_tcp_t *tcp, opj_pi_iterato
@param cblksty @param cblksty
@param first @param first
*/ */
static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first); static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first);
/** /**
Decode a packet of a tile from a source buffer Decode a packet of a tile from a source buffer
@param t2 T2 handle @param t2 T2 handle
@ -296,9 +296,17 @@ static int t2_encode_packet(opj_tcd_tile_t * tile, opj_tcp_t * tcp, opj_pi_itera
return (c - dest); return (c - dest);
} }
static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) { static opj_bool t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int first) {
opj_tcd_seg_t* seg; opj_tcd_seg_t* seg;
cblk->segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t)); opj_tcd_seg_t* segs;
segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs, (index + 1) * sizeof(opj_tcd_seg_t));
if (segs == NULL)
{
return OPJ_FALSE;
}
cblk->segs = segs;
seg = &cblk->segs[index]; seg = &cblk->segs[index];
seg->data = NULL; seg->data = NULL;
seg->dataindex = 0; seg->dataindex = 0;
@ -316,6 +324,8 @@ static void t2_init_seg(opj_tcd_cblk_dec_t* cblk, int index, int cblksty, int fi
} else { } else {
seg->maxpasses = 109; seg->maxpasses = 109;
} }
return OPJ_TRUE;
} }
static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile, static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_tile_t *tile,
@ -462,12 +472,22 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
cblk->numlenbits += increment; cblk->numlenbits += increment;
segno = 0; segno = 0;
if (!cblk->numsegs) { if (!cblk->numsegs) {
t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1); if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 1))
{
opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
bio_destroy(bio);
return -999;
}
} else { } else {
segno = cblk->numsegs - 1; segno = cblk->numsegs - 1;
if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) { if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) {
++segno; ++segno;
t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0); if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0))
{
opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
bio_destroy(bio);
return -999;
}
} }
} }
n = cblk->numnewpasses; n = cblk->numnewpasses;
@ -478,7 +498,12 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
n -= cblk->segs[segno].numnewpasses; n -= cblk->segs[segno].numnewpasses;
if (n > 0) { if (n > 0) {
++segno; ++segno;
t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0); if (!t2_init_seg(cblk, segno, tcp->tccps[compno].cblksty, 0))
{
opj_event_msg(t2->cinfo, EVT_ERROR, "Out of memory\n");
bio_destroy(bio);
return -999;
}
} }
} while (n > 0); } while (n > 0);
} }
@ -714,7 +739,11 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj
} else { } else {
e = 0; e = 0;
} }
if(e == -999) return -999; if(e == -999)
{
pi_destroy(pi, cp, tileno);
return -999;
}
/* progression in resolution */ /* progression in resolution */
image->comps[pi[pino].compno].resno_decoded = image->comps[pi[pino].compno].resno_decoded =
(e > 0) ? (e > 0) ?

View File

@ -615,7 +615,7 @@ void tcd_malloc_decode(opj_tcd_t *tcd, opj_image_t * image, opj_cp_t * cp) {
tcd->image = image; tcd->image = image;
tcd->tcd_image->tw = cp->tw; tcd->tcd_image->tw = cp->tw;
tcd->tcd_image->th = cp->th; tcd->tcd_image->th = cp->th;
tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_malloc(cp->tw * cp->th * sizeof(opj_tcd_tile_t)); tcd->tcd_image->tiles = (opj_tcd_tile_t *) opj_calloc(cp->tw * cp->th, sizeof(opj_tcd_tile_t));
/* /*
Allocate place to store the decoded data = final image Allocate place to store the decoded data = final image
@ -1377,10 +1377,23 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
t1_time = opj_clock(); /* time needed to decode a tile */ t1_time = opj_clock(); /* time needed to decode a tile */
t1 = t1_create(tcd->cinfo); t1 = t1_create(tcd->cinfo);
if (t1 == NULL)
{
opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
t1_destroy(t1);
return OPJ_FALSE;
}
for (compno = 0; compno < tile->numcomps; ++compno) { for (compno = 0; compno < tile->numcomps; ++compno) {
opj_tcd_tilecomp_t* tilec = &tile->comps[compno]; opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
/* The +3 is headroom required by the vectorized DWT */ /* The +3 is headroom required by the vectorized DWT */
tilec->data = (int*) opj_aligned_malloc((((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0))+3) * sizeof(int)); tilec->data = (int*) opj_aligned_malloc((((tilec->x1 - tilec->x0) * (tilec->y1 - tilec->y0))+3) * sizeof(int));
if (tilec->data == NULL)
{
opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
return OPJ_FALSE;
}
t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]); t1_decode_cblks(t1, tilec, &tcd->tcp->tccps[compno]);
} }
t1_destroy(t1); t1_destroy(t1);
@ -1460,6 +1473,11 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
if(!imagec->data){ if(!imagec->data){
imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int)); imagec->data = (int*) opj_malloc(imagec->w * imagec->h * sizeof(int));
} }
if (!imagec->data)
{
opj_event_msg(tcd->cinfo, EVT_ERROR, "Out of memory\n");
return OPJ_FALSE;
}
if(tcd->tcp->tccps[compno].qmfbid == 1) { if(tcd->tcp->tccps[compno].qmfbid == 1) {
for(j = res->y0; j < res->y1; ++j) { for(j = res->y0; j < res->y1; ++j) {
for(i = res->x0; i < res->x1; ++i) { for(i = res->x0; i < res->x1; ++i) {
@ -1493,32 +1511,51 @@ opj_bool tcd_decode_tile(opj_tcd_t *tcd, unsigned char *src, int len, int tileno
void tcd_free_decode(opj_tcd_t *tcd) { void tcd_free_decode(opj_tcd_t *tcd) {
opj_tcd_image_t *tcd_image = tcd->tcd_image; opj_tcd_image_t *tcd_image = tcd->tcd_image;
int i = 0;
for (i = 0; i < tcd_image->tw * tcd_image->th; i++)
{
tcd_free_decode_tile(tcd, i);
}
opj_free(tcd_image->tiles); opj_free(tcd_image->tiles);
} }
void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) { void tcd_free_decode_tile(opj_tcd_t *tcd, int tileno) {
int compno,resno,bandno,precno; int compno,resno,bandno,precno,cblkno;
opj_tcd_image_t *tcd_image = tcd->tcd_image; opj_tcd_image_t *tcd_image = tcd->tcd_image;
opj_tcd_tile_t *tile = &tcd_image->tiles[tileno]; opj_tcd_tile_t *tile = &tcd_image->tiles[tileno];
for (compno = 0; compno < tile->numcomps; compno++) { if (tile->comps != NULL) {
opj_tcd_tilecomp_t *tilec = &tile->comps[compno]; for (compno = 0; compno < tile->numcomps; compno++) {
for (resno = 0; resno < tilec->numresolutions; resno++) { opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
opj_tcd_resolution_t *res = &tilec->resolutions[resno]; for (resno = 0; resno < tilec->numresolutions; resno++) {
for (bandno = 0; bandno < res->numbands; bandno++) { opj_tcd_resolution_t *res = &tilec->resolutions[resno];
opj_tcd_band_t *band = &res->bands[bandno]; for (bandno = 0; bandno < res->numbands; bandno++) {
for (precno = 0; precno < res->ph * res->pw; precno++) { opj_tcd_band_t *band = &res->bands[bandno];
opj_tcd_precinct_t *prec = &band->precincts[precno]; for (precno = 0; precno < res->ph * res->pw; precno++) {
if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree); opj_tcd_precinct_t *prec = &band->precincts[precno];
if (prec->incltree != NULL) tgt_destroy(prec->incltree); if (prec->cblks.dec != NULL) {
for (cblkno = 0; cblkno < prec->cw * prec->ch; ++cblkno) {
opj_tcd_cblk_dec_t* cblk = &prec->cblks.dec[cblkno];
opj_free(cblk->data);
opj_free(cblk->segs);
}
opj_free(prec->cblks.dec);
}
if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree);
if (prec->incltree != NULL) tgt_destroy(prec->incltree);
}
opj_free(band->precincts);
} }
opj_free(band->precincts);
} }
opj_free(tilec->resolutions);
} }
opj_free(tilec->resolutions); opj_free(tile->comps);
tile->comps = NULL;
} }
opj_free(tile->comps);
} }