[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 */
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));
if (cp->tileno == NULL)
{
opj_event_msg(j2k->cinfo, EVT_ERROR, "Out of memory\n");
return;
}
cp->tileno_size = 0;
#ifdef USE_JPWL
@ -1737,6 +1747,14 @@ void j2k_destroy_decompress(opj_j2k_t *j2k) {
opj_free(j2k->tile_len);
}
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);
}
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);
}
if (j2k->state & J2K_STATE_ERR)
{
opj_image_destroy(image);
return NULL;
}
if (j2k->state == J2K_STATE_MT) {
break;

View File

@ -1577,6 +1577,7 @@ void t1_decode_cblks(
opj_free(cblk->segs);
} /* cblkno */
opj_free(precinct->cblks.dec);
precinct->cblks.dec = NULL;
} /* precno */
} /* bandno */
} /* 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 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
@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);
}
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;
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->data = NULL;
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 {
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,
@ -462,12 +472,22 @@ static int t2_decode_packet(opj_t2_t* t2, unsigned char *src, int len, opj_tcd_t
cblk->numlenbits += increment;
segno = 0;
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 {
segno = cblk->numsegs - 1;
if (cblk->segs[segno].numpasses == cblk->segs[segno].maxpasses) {
++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;
@ -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;
if (n > 0) {
++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);
}
@ -714,7 +739,11 @@ int t2_decode_packets(opj_t2_t *t2, unsigned char *src, int len, int tileno, opj
} else {
e = 0;
}
if(e == -999) return -999;
if(e == -999)
{
pi_destroy(pi, cp, tileno);
return -999;
}
/* progression in resolution */
image->comps[pi[pino].compno].resno_decoded =
(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->tcd_image->tw = cp->tw;
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
@ -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 = 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) {
opj_tcd_tilecomp_t* tilec = &tile->comps[compno];
/* 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));
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_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){
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) {
for(j = res->y0; j < res->y1; ++j) {
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) {
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);
}
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_tile_t *tile = &tcd_image->tiles[tileno];
for (compno = 0; compno < tile->numcomps; compno++) {
opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
for (resno = 0; resno < tilec->numresolutions; resno++) {
opj_tcd_resolution_t *res = &tilec->resolutions[resno];
for (bandno = 0; bandno < res->numbands; bandno++) {
opj_tcd_band_t *band = &res->bands[bandno];
for (precno = 0; precno < res->ph * res->pw; precno++) {
opj_tcd_precinct_t *prec = &band->precincts[precno];
if (prec->imsbtree != NULL) tgt_destroy(prec->imsbtree);
if (prec->incltree != NULL) tgt_destroy(prec->incltree);
if (tile->comps != NULL) {
for (compno = 0; compno < tile->numcomps; compno++) {
opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
for (resno = 0; resno < tilec->numresolutions; resno++) {
opj_tcd_resolution_t *res = &tilec->resolutions[resno];
for (bandno = 0; bandno < res->numbands; bandno++) {
opj_tcd_band_t *band = &res->bands[bandno];
for (precno = 0; precno < res->ph * res->pw; precno++) {
opj_tcd_precinct_t *prec = &band->precincts[precno];
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);
}