openjpeg/src/lib/openjp2/t2.c

1685 lines
62 KiB
C
Raw Normal View History

2003-11-27 11:10:17 +01:00
/*
* The copyright in this software is being made available under the 2-clauses
* BSD License, included below. This software may be subject to other third
* party and contributor rights, including patent rights, and no such rights
* are granted under this license.
*
* Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
* Copyright (c) 2002-2014, Professor Benoit Macq
* Copyright (c) 2001-2003, David Janssens
* Copyright (c) 2002-2003, Yannick Verschueren
* Copyright (c) 2003-2007, Francois-Olivier Devaux
* Copyright (c) 2003-2014, Antonin Descampe
2007-01-15 10:55:40 +01:00
* Copyright (c) 2005, Herve Drolon, FreeImage Team
* Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
* Copyright (c) 2012, CS Systemes d'Information, France
* Copyright (c) 2017, IntoPIX SA <support@intopix.com>
2003-11-27 11:10:17 +01:00
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "opj_includes.h"
#include "opj_common.h"
2005-12-08 10:38:47 +01:00
/** @defgroup T2 T2 - Implementation of a tier-2 coding */
/*@{*/
/** @name Local static functions */
/*@{*/
static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n);
static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio);
2005-12-08 10:38:47 +01:00
/**
Variable length code for signalling delta Zil (truncation point)
@param bio Bit Input/Output component
@param n delta Zil
2005-12-08 10:38:47 +01:00
*/
static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n);
static OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio);
/**
Encode a packet of a tile to a destination buffer
@param tileno Number of the tile encoded
@param tile Tile for which to write the packets
@param tcp Tile coding parameters
@param pi Packet identity
@param dest Destination buffer
@param p_data_written FIXME DOC
@param len Length of the destination buffer
@param cstr_info Codestream information structure
@param p_t2_mode If == THRESH_CALC In Threshold calculation ,If == FINAL_PASS Final pass
@param p_manager the user event manager
@return
*/
static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno,
opj_tcd_tile_t *tile,
opj_tcp_t *tcp,
opj_pi_iterator_t *pi,
OPJ_BYTE *dest,
OPJ_UINT32 * p_data_written,
OPJ_UINT32 len,
opj_codestream_info_t *cstr_info,
J2K_T2_MODE p_t2_mode,
opj_event_mgr_t *p_manager);
/**
Decode a packet of a tile from a source buffer
@param t2 T2 handle
@param tile Tile for which to write the packets
@param tcp Tile coding parameters
@param pi Packet identity
@param src Source buffer
@param data_read FIXME DOC
@param max_length FIXME DOC
@param pack_info Packet information
@param p_manager the user event manager
@return FIXME DOC
*/
static OPJ_BOOL opj_t2_decode_packet(opj_t2_t* t2,
opj_tcd_tile_t *tile,
opj_tcp_t *tcp,
opj_pi_iterator_t *pi,
OPJ_BYTE *src,
OPJ_UINT32 * data_read,
OPJ_UINT32 max_length,
opj_packet_info_t *pack_info,
opj_event_mgr_t *p_manager);
static OPJ_BOOL opj_t2_skip_packet(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info,
opj_event_mgr_t *p_manager);
static OPJ_BOOL opj_t2_read_packet_header(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BOOL * p_is_data_present,
OPJ_BYTE *p_src_data,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info,
opj_event_mgr_t *p_manager);
static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src_data,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *pack_info,
opj_event_mgr_t *p_manager);
static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_pi_iterator_t *p_pi,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *pack_info,
opj_event_mgr_t *p_manager);
/**
@param cblk
@param index
@param cblksty
@param first
*/
static OPJ_BOOL opj_t2_init_seg(opj_tcd_cblk_dec_t* cblk,
OPJ_UINT32 index,
OPJ_UINT32 cblksty,
OPJ_UINT32 first);
2005-12-08 10:38:47 +01:00
/*@}*/
/*@}*/
/* ----------------------------------------------------------------------- */
/* #define RESTART 0x04 */
static void opj_t2_putcommacode(opj_bio_t *bio, OPJ_INT32 n)
{
while (--n >= 0) {
opj_bio_write(bio, 1, 1);
}
opj_bio_write(bio, 0, 1);
2003-11-27 11:10:17 +01:00
}
static OPJ_UINT32 opj_t2_getcommacode(opj_bio_t *bio)
{
OPJ_UINT32 n = 0;
while (opj_bio_read(bio, 1)) {
++n;
}
return n;
2003-11-27 11:10:17 +01:00
}
static void opj_t2_putnumpasses(opj_bio_t *bio, OPJ_UINT32 n)
{
if (n == 1) {
opj_bio_write(bio, 0, 1);
} else if (n == 2) {
opj_bio_write(bio, 2, 2);
} else if (n <= 5) {
opj_bio_write(bio, 0xc | (n - 3), 4);
} else if (n <= 36) {
opj_bio_write(bio, 0x1e0 | (n - 6), 9);
} else if (n <= 164) {
opj_bio_write(bio, 0xff80 | (n - 37), 16);
}
2003-11-27 11:10:17 +01:00
}
static OPJ_UINT32 opj_t2_getnumpasses(opj_bio_t *bio)
{
OPJ_UINT32 n;
if (!opj_bio_read(bio, 1)) {
return 1;
}
if (!opj_bio_read(bio, 1)) {
return 2;
}
if ((n = opj_bio_read(bio, 2)) != 3) {
return (3 + n);
}
if ((n = opj_bio_read(bio, 5)) != 31) {
return (6 + n);
}
return (37 + opj_bio_read(bio, 7));
2003-11-27 11:10:17 +01:00
}
/* ----------------------------------------------------------------------- */
2004-02-13 10:47:40 +01:00
OPJ_BOOL opj_t2_encode_packets(opj_t2_t* p_t2,
OPJ_UINT32 p_tile_no,
opj_tcd_tile_t *p_tile,
OPJ_UINT32 p_maxlayers,
OPJ_BYTE *p_dest,
OPJ_UINT32 * p_data_written,
OPJ_UINT32 p_max_len,
opj_codestream_info_t *cstr_info,
Add support for generation of PLT markers in encoder * -PLT switch added to opj_compress * Add a opj_encoder_set_extra_options() function that accepts a PLT=YES option, and could be expanded later for other uses. ------- Testing with a Sentinel2 10m band, T36JTT_20160914T074612_B02.jp2, coming from S2A_MSIL1C_20160914T074612_N0204_R135_T36JTT_20160914T081456.SAFE Decompress it to TIFF: ``` opj_uncompress -i T36JTT_20160914T074612_B02.jp2 -o T36JTT_20160914T074612_B02.tif ``` Recompress it with similar parameters as original: ``` opj_compress -n 5 -c [256,256],[256,256],[256,256],[256,256],[256,256] -t 1024,1024 -PLT -i T36JTT_20160914T074612_B02.tif -o T36JTT_20160914T074612_B02_PLT.jp2 ``` Dump codestream detail with GDAL dump_jp2.py utility (https://github.com/OSGeo/gdal/blob/master/gdal/swig/python/samples/dump_jp2.py) ``` python dump_jp2.py T36JTT_20160914T074612_B02.jp2 > /tmp/dump_sentinel2_ori.txt python dump_jp2.py T36JTT_20160914T074612_B02_PLT.jp2 > /tmp/dump_sentinel2_openjpeg_plt.txt ``` The diff between both show very similar structure, and identical number of packets in PLT markers Now testing with Kakadu (KDU803_Demo_Apps_for_Linux-x86-64_200210) Full file decompression: ``` kdu_expand -i T36JTT_20160914T074612_B02_PLT.jp2 -o tmp.tif Consumed 121 tile-part(s) from a total of 121 tile(s). Consumed 80,318,806 codestream bytes (excluding any file format) = 5.329697 bits/pel. Processed using the multi-threaded environment, with 8 parallel threads of execution ``` Partial decompresson (presumably using PLT markers): ``` kdu_expand -i T36JTT_20160914T074612_B02.jp2 -o tmp.pgm -region "{0.5,0.5},{0.01,0.01}" kdu_expand -i T36JTT_20160914T074612_B02_PLT.jp2 -o tmp2.pgm -region "{0.5,0.5},{0.01,0.01}" diff tmp.pgm tmp2.pgm && echo "same !" ``` ------- Funded by ESA for S2-MPC project
2020-04-21 15:55:44 +02:00
opj_tcd_marker_info_t* p_marker_info,
OPJ_UINT32 p_tp_num,
OPJ_INT32 p_tp_pos,
OPJ_UINT32 p_pino,
J2K_T2_MODE p_t2_mode,
opj_event_mgr_t *p_manager)
{
OPJ_BYTE *l_current_data = p_dest;
OPJ_UINT32 l_nb_bytes = 0;
OPJ_UINT32 compno;
OPJ_UINT32 poc;
opj_pi_iterator_t *l_pi = 00;
opj_pi_iterator_t *l_current_pi = 00;
opj_image_t *l_image = p_t2->image;
opj_cp_t *l_cp = p_t2->cp;
opj_tcp_t *l_tcp = &l_cp->tcps[p_tile_no];
OPJ_UINT32 pocno = (l_cp->rsiz == OPJ_PROFILE_CINEMA_4K) ? 2 : 1;
OPJ_UINT32 l_max_comp = l_cp->m_specific_param.m_enc.m_max_comp_size > 0 ?
l_image->numcomps : 1;
OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1;
l_pi = opj_pi_initialise_encode(l_image, l_cp, p_tile_no, p_t2_mode, p_manager);
if (!l_pi) {
return OPJ_FALSE;
}
* p_data_written = 0;
if (p_t2_mode == THRESH_CALC) { /* Calculating threshold */
l_current_pi = l_pi;
for (compno = 0; compno < l_max_comp; ++compno) {
OPJ_UINT32 l_comp_len = 0;
l_current_pi = l_pi;
for (poc = 0; poc < pocno ; ++poc) {
OPJ_UINT32 l_tp_num = compno;
/* TODO MSD : check why this function cannot fail (cf. v1) */
opj_pi_create_encode(l_pi, l_cp, p_tile_no, poc, l_tp_num, p_tp_pos, p_t2_mode);
if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) {
/* TODO ADE : add an error */
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_FALSE;
}
while (opj_pi_next(l_current_pi)) {
if (l_current_pi->layno < p_maxlayers) {
l_nb_bytes = 0;
if (! opj_t2_encode_packet(p_tile_no, p_tile, l_tcp, l_current_pi,
l_current_data, &l_nb_bytes,
p_max_len, cstr_info,
p_t2_mode,
p_manager)) {
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_FALSE;
}
l_comp_len += l_nb_bytes;
l_current_data += l_nb_bytes;
p_max_len -= l_nb_bytes;
* p_data_written += l_nb_bytes;
}
}
if (l_cp->m_specific_param.m_enc.m_max_comp_size) {
if (l_comp_len > l_cp->m_specific_param.m_enc.m_max_comp_size) {
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_FALSE;
}
}
++l_current_pi;
}
}
} else { /* t2_mode == FINAL_PASS */
opj_pi_create_encode(l_pi, l_cp, p_tile_no, p_pino, p_tp_num, p_tp_pos,
p_t2_mode);
l_current_pi = &l_pi[p_pino];
if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) {
/* TODO ADE : add an error */
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_FALSE;
}
Add support for generation of PLT markers in encoder * -PLT switch added to opj_compress * Add a opj_encoder_set_extra_options() function that accepts a PLT=YES option, and could be expanded later for other uses. ------- Testing with a Sentinel2 10m band, T36JTT_20160914T074612_B02.jp2, coming from S2A_MSIL1C_20160914T074612_N0204_R135_T36JTT_20160914T081456.SAFE Decompress it to TIFF: ``` opj_uncompress -i T36JTT_20160914T074612_B02.jp2 -o T36JTT_20160914T074612_B02.tif ``` Recompress it with similar parameters as original: ``` opj_compress -n 5 -c [256,256],[256,256],[256,256],[256,256],[256,256] -t 1024,1024 -PLT -i T36JTT_20160914T074612_B02.tif -o T36JTT_20160914T074612_B02_PLT.jp2 ``` Dump codestream detail with GDAL dump_jp2.py utility (https://github.com/OSGeo/gdal/blob/master/gdal/swig/python/samples/dump_jp2.py) ``` python dump_jp2.py T36JTT_20160914T074612_B02.jp2 > /tmp/dump_sentinel2_ori.txt python dump_jp2.py T36JTT_20160914T074612_B02_PLT.jp2 > /tmp/dump_sentinel2_openjpeg_plt.txt ``` The diff between both show very similar structure, and identical number of packets in PLT markers Now testing with Kakadu (KDU803_Demo_Apps_for_Linux-x86-64_200210) Full file decompression: ``` kdu_expand -i T36JTT_20160914T074612_B02_PLT.jp2 -o tmp.tif Consumed 121 tile-part(s) from a total of 121 tile(s). Consumed 80,318,806 codestream bytes (excluding any file format) = 5.329697 bits/pel. Processed using the multi-threaded environment, with 8 parallel threads of execution ``` Partial decompresson (presumably using PLT markers): ``` kdu_expand -i T36JTT_20160914T074612_B02.jp2 -o tmp.pgm -region "{0.5,0.5},{0.01,0.01}" kdu_expand -i T36JTT_20160914T074612_B02_PLT.jp2 -o tmp2.pgm -region "{0.5,0.5},{0.01,0.01}" diff tmp.pgm tmp2.pgm && echo "same !" ``` ------- Funded by ESA for S2-MPC project
2020-04-21 15:55:44 +02:00
if (p_marker_info && p_marker_info->need_PLT) {
/* One time use intended */
assert(p_marker_info->packet_count == 0);
assert(p_marker_info->p_packet_size == NULL);
p_marker_info->p_packet_size = (OPJ_UINT32*) opj_malloc(
opj_get_encoding_packet_count(l_image, l_cp, p_tile_no) * sizeof(OPJ_UINT32));
if (p_marker_info->p_packet_size == NULL) {
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_FALSE;
}
}
while (opj_pi_next(l_current_pi)) {
if (l_current_pi->layno < p_maxlayers) {
l_nb_bytes = 0;
if (! opj_t2_encode_packet(p_tile_no, p_tile, l_tcp, l_current_pi,
l_current_data, &l_nb_bytes, p_max_len,
cstr_info, p_t2_mode, p_manager)) {
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_FALSE;
}
l_current_data += l_nb_bytes;
p_max_len -= l_nb_bytes;
* p_data_written += l_nb_bytes;
Add support for generation of PLT markers in encoder * -PLT switch added to opj_compress * Add a opj_encoder_set_extra_options() function that accepts a PLT=YES option, and could be expanded later for other uses. ------- Testing with a Sentinel2 10m band, T36JTT_20160914T074612_B02.jp2, coming from S2A_MSIL1C_20160914T074612_N0204_R135_T36JTT_20160914T081456.SAFE Decompress it to TIFF: ``` opj_uncompress -i T36JTT_20160914T074612_B02.jp2 -o T36JTT_20160914T074612_B02.tif ``` Recompress it with similar parameters as original: ``` opj_compress -n 5 -c [256,256],[256,256],[256,256],[256,256],[256,256] -t 1024,1024 -PLT -i T36JTT_20160914T074612_B02.tif -o T36JTT_20160914T074612_B02_PLT.jp2 ``` Dump codestream detail with GDAL dump_jp2.py utility (https://github.com/OSGeo/gdal/blob/master/gdal/swig/python/samples/dump_jp2.py) ``` python dump_jp2.py T36JTT_20160914T074612_B02.jp2 > /tmp/dump_sentinel2_ori.txt python dump_jp2.py T36JTT_20160914T074612_B02_PLT.jp2 > /tmp/dump_sentinel2_openjpeg_plt.txt ``` The diff between both show very similar structure, and identical number of packets in PLT markers Now testing with Kakadu (KDU803_Demo_Apps_for_Linux-x86-64_200210) Full file decompression: ``` kdu_expand -i T36JTT_20160914T074612_B02_PLT.jp2 -o tmp.tif Consumed 121 tile-part(s) from a total of 121 tile(s). Consumed 80,318,806 codestream bytes (excluding any file format) = 5.329697 bits/pel. Processed using the multi-threaded environment, with 8 parallel threads of execution ``` Partial decompresson (presumably using PLT markers): ``` kdu_expand -i T36JTT_20160914T074612_B02.jp2 -o tmp.pgm -region "{0.5,0.5},{0.01,0.01}" kdu_expand -i T36JTT_20160914T074612_B02_PLT.jp2 -o tmp2.pgm -region "{0.5,0.5},{0.01,0.01}" diff tmp.pgm tmp2.pgm && echo "same !" ``` ------- Funded by ESA for S2-MPC project
2020-04-21 15:55:44 +02:00
if (p_marker_info && p_marker_info->need_PLT) {
p_marker_info->p_packet_size[p_marker_info->packet_count] = l_nb_bytes;
p_marker_info->packet_count ++;
}
/* INDEX >> */
if (cstr_info) {
if (cstr_info->index_write) {
opj_tile_info_t *info_TL = &cstr_info->tile[p_tile_no];
opj_packet_info_t *info_PK = &info_TL->packet[cstr_info->packno];
if (!cstr_info->packno) {
info_PK->start_pos = info_TL->end_header + 1;
} else {
info_PK->start_pos = ((l_cp->m_specific_param.m_enc.m_tp_on | l_tcp->POC) &&
info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[cstr_info->packno -
1].end_pos + 1;
}
info_PK->end_pos = info_PK->start_pos + l_nb_bytes - 1;
info_PK->end_ph_pos += info_PK->start_pos -
1; /* End of packet header which now only represents the distance
to start of packet is incremented by value of start of packet*/
}
cstr_info->packno++;
}
/* << INDEX */
++p_tile->packno;
}
}
}
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_TRUE;
}
/* see issue 80 */
#if 0
#define JAS_FPRINTF fprintf
#else
/* issue 290 */
static void opj_null_jas_fprintf(FILE* file, const char * format, ...)
{
(void)file;
(void)format;
}
#define JAS_FPRINTF opj_null_jas_fprintf
#endif
OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd,
opj_t2_t *p_t2,
OPJ_UINT32 p_tile_no,
opj_tcd_tile_t *p_tile,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_len,
opj_codestream_index_t *p_cstr_index,
opj_event_mgr_t *p_manager)
{
OPJ_BYTE *l_current_data = p_src;
opj_pi_iterator_t *l_pi = 00;
OPJ_UINT32 pino;
opj_image_t *l_image = p_t2->image;
opj_cp_t *l_cp = p_t2->cp;
opj_tcp_t *l_tcp = &(p_t2->cp->tcps[p_tile_no]);
OPJ_UINT32 l_nb_bytes_read;
OPJ_UINT32 l_nb_pocs = l_tcp->numpocs + 1;
opj_pi_iterator_t *l_current_pi = 00;
#ifdef TODO_MSD
OPJ_UINT32 curtp = 0;
OPJ_UINT32 tp_start_packno;
#endif
opj_packet_info_t *l_pack_info = 00;
opj_image_comp_t* l_img_comp = 00;
OPJ_ARG_NOT_USED(p_cstr_index);
#ifdef TODO_MSD
if (p_cstr_index) {
l_pack_info = p_cstr_index->tile_index[p_tile_no].packet;
}
#endif
/* create a packet iterator */
l_pi = opj_pi_create_decode(l_image, l_cp, p_tile_no, p_manager);
if (!l_pi) {
return OPJ_FALSE;
}
l_current_pi = l_pi;
for (pino = 0; pino <= l_tcp->numpocs; ++pino) {
/* if the resolution needed is too low, one dim of the tilec could be equal to zero
* and no packets are used to decode this resolution and
* l_current_pi->resno is always >= p_tile->comps[l_current_pi->compno].minimum_num_resolutions
* and no l_img_comp->resno_decoded are computed
*/
OPJ_BOOL* first_pass_failed = NULL;
if (l_current_pi->poc.prg == OPJ_PROG_UNKNOWN) {
/* TODO ADE : add an error */
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_FALSE;
}
first_pass_failed = (OPJ_BOOL*)opj_malloc(l_image->numcomps * sizeof(OPJ_BOOL));
if (!first_pass_failed) {
opj_pi_destroy(l_pi, l_nb_pocs);
return OPJ_FALSE;
}
memset(first_pass_failed, OPJ_TRUE, l_image->numcomps * sizeof(OPJ_BOOL));
while (opj_pi_next(l_current_pi)) {
OPJ_BOOL skip_packet = OPJ_FALSE;
JAS_FPRINTF(stderr,
"packet offset=00000166 prg=%d cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d\n\n",
l_current_pi->poc.prg1, l_current_pi->compno, l_current_pi->resno,
l_current_pi->precno, l_current_pi->layno);
/* If the packet layer is greater or equal than the maximum */
/* number of layers, skip the packet */
if (l_current_pi->layno >= l_tcp->num_layers_to_decode) {
skip_packet = OPJ_TRUE;
}
/* If the packet resolution number is greater than the minimum */
/* number of resolution allowed, skip the packet */
else if (l_current_pi->resno >=
p_tile->comps[l_current_pi->compno].minimum_num_resolutions) {
skip_packet = OPJ_TRUE;
} else {
/* If no precincts of any band intersects the area of interest, */
/* skip the packet */
OPJ_UINT32 bandno;
opj_tcd_tilecomp_t *tilec = &p_tile->comps[l_current_pi->compno];
opj_tcd_resolution_t *res = &tilec->resolutions[l_current_pi->resno];
skip_packet = OPJ_TRUE;
for (bandno = 0; bandno < res->numbands; ++bandno) {
opj_tcd_band_t* band = &res->bands[bandno];
opj_tcd_precinct_t* prec = &band->precincts[l_current_pi->precno];
if (opj_tcd_is_subband_area_of_interest(tcd,
l_current_pi->compno,
l_current_pi->resno,
band->bandno,
(OPJ_UINT32)prec->x0,
(OPJ_UINT32)prec->y0,
(OPJ_UINT32)prec->x1,
(OPJ_UINT32)prec->y1)) {
skip_packet = OPJ_FALSE;
break;
}
}
/*
printf("packet cmptno=%02d rlvlno=%02d prcno=%03d lyrno=%02d -> %s\n",
l_current_pi->compno, l_current_pi->resno,
l_current_pi->precno, l_current_pi->layno, skip_packet ? "skipped" : "kept");
*/
}
if (!skip_packet) {
l_nb_bytes_read = 0;
first_pass_failed[l_current_pi->compno] = OPJ_FALSE;
if (! opj_t2_decode_packet(p_t2, p_tile, l_tcp, l_current_pi, l_current_data,
&l_nb_bytes_read, p_max_len, l_pack_info, p_manager)) {
opj_pi_destroy(l_pi, l_nb_pocs);
opj_free(first_pass_failed);
return OPJ_FALSE;
}
l_img_comp = &(l_image->comps[l_current_pi->compno]);
l_img_comp->resno_decoded = opj_uint_max(l_current_pi->resno,
l_img_comp->resno_decoded);
} else {
l_nb_bytes_read = 0;
if (! opj_t2_skip_packet(p_t2, p_tile, l_tcp, l_current_pi, l_current_data,
&l_nb_bytes_read, p_max_len, l_pack_info, p_manager)) {
opj_pi_destroy(l_pi, l_nb_pocs);
opj_free(first_pass_failed);
return OPJ_FALSE;
}
}
if (first_pass_failed[l_current_pi->compno]) {
l_img_comp = &(l_image->comps[l_current_pi->compno]);
if (l_img_comp->resno_decoded == 0) {
l_img_comp->resno_decoded =
p_tile->comps[l_current_pi->compno].minimum_num_resolutions - 1;
}
}
l_current_data += l_nb_bytes_read;
p_max_len -= l_nb_bytes_read;
/* INDEX >> */
#ifdef TODO_MSD
if (p_cstr_info) {
opj_tile_info_v2_t *info_TL = &p_cstr_info->tile[p_tile_no];
opj_packet_info_t *info_PK = &info_TL->packet[p_cstr_info->packno];
tp_start_packno = 0;
if (!p_cstr_info->packno) {
info_PK->start_pos = info_TL->end_header + 1;
} else if (info_TL->packet[p_cstr_info->packno - 1].end_pos >=
(OPJ_INT32)
p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_pos) { /* New tile part */
info_TL->tp[curtp].tp_numpacks = p_cstr_info->packno -
tp_start_packno; /* Number of packets in previous tile-part */
tp_start_packno = p_cstr_info->packno;
curtp++;
info_PK->start_pos = p_cstr_info->tile[p_tile_no].tp[curtp].tp_end_header + 1;
} else {
info_PK->start_pos = (l_cp->m_specific_param.m_enc.m_tp_on &&
info_PK->start_pos) ? info_PK->start_pos : info_TL->packet[p_cstr_info->packno -
1].end_pos + 1;
}
info_PK->end_pos = info_PK->start_pos + l_nb_bytes_read - 1;
info_PK->end_ph_pos += info_PK->start_pos -
1; /* End of packet header which now only represents the distance */
++p_cstr_info->packno;
}
#endif
/* << INDEX */
}
++l_current_pi;
opj_free(first_pass_failed);
}
/* INDEX >> */
#ifdef TODO_MSD
if
(p_cstr_info) {
p_cstr_info->tile[p_tile_no].tp[curtp].tp_numpacks = p_cstr_info->packno -
tp_start_packno; /* Number of packets in last tile-part */
}
#endif
/* << INDEX */
/* don't forget to release pi */
opj_pi_destroy(l_pi, l_nb_pocs);
*p_data_read = (OPJ_UINT32)(l_current_data - p_src);
return OPJ_TRUE;
}
/* ----------------------------------------------------------------------- */
/**
* Creates a Tier 2 handle
*
* @param p_image Source or destination image
* @param p_cp Image coding parameters.
* @return a new T2 handle if successful, NULL otherwise.
*/
opj_t2_t* opj_t2_create(opj_image_t *p_image, opj_cp_t *p_cp)
{
/* create the t2 structure */
opj_t2_t *l_t2 = (opj_t2_t*)opj_calloc(1, sizeof(opj_t2_t));
if (!l_t2) {
return NULL;
}
l_t2->image = p_image;
l_t2->cp = p_cp;
return l_t2;
}
void opj_t2_destroy(opj_t2_t *t2)
{
if (t2) {
opj_free(t2);
}
}
static OPJ_BOOL opj_t2_decode_packet(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info,
opj_event_mgr_t *p_manager)
{
OPJ_BOOL l_read_data;
OPJ_UINT32 l_nb_bytes_read = 0;
OPJ_UINT32 l_nb_total_bytes_read = 0;
*p_data_read = 0;
if (! opj_t2_read_packet_header(p_t2, p_tile, p_tcp, p_pi, &l_read_data, p_src,
&l_nb_bytes_read, p_max_length, p_pack_info, p_manager)) {
return OPJ_FALSE;
}
p_src += l_nb_bytes_read;
l_nb_total_bytes_read += l_nb_bytes_read;
p_max_length -= l_nb_bytes_read;
/* we should read data for the packet */
if (l_read_data) {
l_nb_bytes_read = 0;
if (! opj_t2_read_packet_data(p_t2, p_tile, p_pi, p_src, &l_nb_bytes_read,
p_max_length, p_pack_info, p_manager)) {
return OPJ_FALSE;
}
l_nb_total_bytes_read += l_nb_bytes_read;
}
*p_data_read = l_nb_total_bytes_read;
return OPJ_TRUE;
}
static OPJ_BOOL opj_t2_encode_packet(OPJ_UINT32 tileno,
opj_tcd_tile_t * tile,
opj_tcp_t * tcp,
opj_pi_iterator_t *pi,
OPJ_BYTE *dest,
OPJ_UINT32 * p_data_written,
OPJ_UINT32 length,
opj_codestream_info_t *cstr_info,
J2K_T2_MODE p_t2_mode,
opj_event_mgr_t *p_manager)
{
OPJ_UINT32 bandno, cblkno;
OPJ_BYTE* c = dest;
OPJ_UINT32 l_nb_bytes;
OPJ_UINT32 compno = pi->compno; /* component value */
OPJ_UINT32 resno = pi->resno; /* resolution level value */
OPJ_UINT32 precno = pi->precno; /* precinct value */
OPJ_UINT32 layno = pi->layno; /* quality layer value */
OPJ_UINT32 l_nb_blocks;
opj_tcd_band_t *band = 00;
opj_tcd_cblk_enc_t* cblk = 00;
opj_tcd_pass_t *pass = 00;
opj_tcd_tilecomp_t *tilec = &tile->comps[compno];
opj_tcd_resolution_t *res = &tilec->resolutions[resno];
opj_bio_t *bio = 00; /* BIO component */
#ifdef ENABLE_EMPTY_PACKET_OPTIMIZATION
OPJ_BOOL packet_empty = OPJ_TRUE;
#else
OPJ_BOOL packet_empty = OPJ_FALSE;
#endif
#ifdef DEBUG_VERBOSE
if (p_t2_mode == FINAL_PASS) {
fprintf(stderr,
"encode packet compono=%d, resno=%d, precno=%d, layno=%d\n",
compno, resno, precno, layno);
}
#endif
/* <SOP 0xff91> */
if (tcp->csty & J2K_CP_CSTY_SOP) {
if (length < 6) {
if (p_t2_mode == FINAL_PASS) {
opj_event_msg(p_manager, EVT_ERROR,
"opj_t2_encode_packet(): only %u bytes remaining in "
"output buffer. %u needed.\n",
length, 6);
}
return OPJ_FALSE;
}
c[0] = 255;
c[1] = 145;
c[2] = 0;
c[3] = 4;
#if 0
c[4] = (tile->packno % 65536) / 256;
c[5] = (tile->packno % 65536) % 256;
#else
c[4] = (tile->packno >> 8) & 0xff; /* packno is uint32_t */
c[5] = tile->packno & 0xff;
#endif
c += 6;
length -= 6;
}
/* </SOP> */
if (!layno) {
band = res->bands;
for (bandno = 0; bandno < res->numbands; ++bandno, ++band) {
opj_tcd_precinct_t *prc;
/* Skip empty bands */
if (opj_tcd_is_band_empty(band)) {
continue;
}
/* Avoid out of bounds access of https://github.com/uclouvain/openjpeg/issues/1294 */
/* but likely not a proper fix. */
if (precno >= res->pw * res->ph) {
opj_event_msg(p_manager, EVT_ERROR,
"opj_t2_encode_packet(): accessing precno=%u >= %u\n",
precno, res->pw * res->ph);
return OPJ_FALSE;
}
prc = &band->precincts[precno];
opj_tgt_reset(prc->incltree);
opj_tgt_reset(prc->imsbtree);
l_nb_blocks = prc->cw * prc->ch;
for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) {
cblk = &prc->cblks.enc[cblkno];
cblk->numpasses = 0;
opj_tgt_setvalue(prc->imsbtree, cblkno, band->numbps - (OPJ_INT32)cblk->numbps);
}
}
}
bio = opj_bio_create();
if (!bio) {
/* FIXME event manager error callback */
return OPJ_FALSE;
}
opj_bio_init_enc(bio, c, length);
#ifdef ENABLE_EMPTY_PACKET_OPTIMIZATION
/* WARNING: this code branch is disabled, since it has been reported that */
/* such packets cause decoding issues with cinema J2K hardware */
/* decoders: https://groups.google.com/forum/#!topic/openjpeg/M7M_fLX_Bco */
/* Check if the packet is empty */
/* Note: we could also skip that step and always write a packet header */
band = res->bands;
for (bandno = 0; bandno < res->numbands; ++bandno, ++band) {
opj_tcd_precinct_t *prc;
/* Skip empty bands */
if (opj_tcd_is_band_empty(band)) {
continue;
}
prc = &band->precincts[precno];
l_nb_blocks = prc->cw * prc->ch;
cblk = prc->cblks.enc;
for (cblkno = 0; cblkno < l_nb_blocks; cblkno++, ++cblk) {
opj_tcd_layer_t *layer = &cblk->layers[layno];
/* if cblk not included, go to the next cblk */
if (!layer->numpasses) {
continue;
}
packet_empty = OPJ_FALSE;
break;
}
if (!packet_empty) {
break;
}
}
#endif
opj_bio_write(bio, packet_empty ? 0 : 1, 1); /* Empty header bit */
/* Writing Packet header */
band = res->bands;
for (bandno = 0; !packet_empty &&
bandno < res->numbands; ++bandno, ++band) {
opj_tcd_precinct_t *prc;
/* Skip empty bands */
if (opj_tcd_is_band_empty(band)) {
continue;
}
/* Avoid out of bounds access of https://github.com/uclouvain/openjpeg/issues/1297 */
/* but likely not a proper fix. */
if (precno >= res->pw * res->ph) {
opj_event_msg(p_manager, EVT_ERROR,
"opj_t2_encode_packet(): accessing precno=%u >= %u\n",
precno, res->pw * res->ph);
return OPJ_FALSE;
}
prc = &band->precincts[precno];
l_nb_blocks = prc->cw * prc->ch;
cblk = prc->cblks.enc;
for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) {
opj_tcd_layer_t *layer = &cblk->layers[layno];
if (!cblk->numpasses && layer->numpasses) {
opj_tgt_setvalue(prc->incltree, cblkno, (OPJ_INT32)layno);
}
++cblk;
}
cblk = prc->cblks.enc;
for (cblkno = 0; cblkno < l_nb_blocks; cblkno++) {
opj_tcd_layer_t *layer = &cblk->layers[layno];
OPJ_UINT32 increment = 0;
OPJ_UINT32 nump = 0;
OPJ_UINT32 len = 0, passno;
OPJ_UINT32 l_nb_passes;
/* cblk inclusion bits */
if (!cblk->numpasses) {
opj_tgt_encode(bio, prc->incltree, cblkno, (OPJ_INT32)(layno + 1));
} else {
opj_bio_write(bio, layer->numpasses != 0, 1);
}
/* if cblk not included, go to the next cblk */
if (!layer->numpasses) {
++cblk;
continue;
}
/* if first instance of cblk --> zero bit-planes information */
if (!cblk->numpasses) {
cblk->numlenbits = 3;
opj_tgt_encode(bio, prc->imsbtree, cblkno, 999);
}
/* number of coding passes included */
opj_t2_putnumpasses(bio, layer->numpasses);
l_nb_passes = cblk->numpasses + layer->numpasses;
pass = cblk->passes + cblk->numpasses;
/* computation of the increase of the length indicator and insertion in the header */
for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) {
++nump;
len += pass->len;
if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) {
increment = (OPJ_UINT32)opj_int_max((OPJ_INT32)increment,
opj_int_floorlog2((OPJ_INT32)len) + 1
- ((OPJ_INT32)cblk->numlenbits + opj_int_floorlog2((OPJ_INT32)nump)));
len = 0;
nump = 0;
}
++pass;
}
opj_t2_putcommacode(bio, (OPJ_INT32)increment);
/* computation of the new Length indicator */
cblk->numlenbits += increment;
pass = cblk->passes + cblk->numpasses;
/* insertion of the codeword segment length */
for (passno = cblk->numpasses; passno < l_nb_passes; ++passno) {
nump++;
len += pass->len;
if (pass->term || passno == (cblk->numpasses + layer->numpasses) - 1) {
opj_bio_write(bio, (OPJ_UINT32)len,
cblk->numlenbits + (OPJ_UINT32)opj_int_floorlog2((OPJ_INT32)nump));
len = 0;
nump = 0;
}
++pass;
}
++cblk;
}
}
if (!opj_bio_flush(bio)) {
opj_bio_destroy(bio);
return OPJ_FALSE; /* modified to eliminate longjmp !! */
}
l_nb_bytes = (OPJ_UINT32)opj_bio_numbytes(bio);
c += l_nb_bytes;
length -= l_nb_bytes;
opj_bio_destroy(bio);
/* <EPH 0xff92> */
if (tcp->csty & J2K_CP_CSTY_EPH) {
if (length < 2) {
if (p_t2_mode == FINAL_PASS) {
opj_event_msg(p_manager, EVT_ERROR,
"opj_t2_encode_packet(): only %u bytes remaining in "
"output buffer. %u needed.\n",
length, 2);
}
return OPJ_FALSE;
}
c[0] = 255;
c[1] = 146;
c += 2;
length -= 2;
}
/* </EPH> */
/* << INDEX */
/* End of packet header position. Currently only represents the distance to start of packet
Will be updated later by incrementing with packet start value*/
if (cstr_info && cstr_info->index_write) {
opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno];
info_PK->end_ph_pos = (OPJ_INT32)(c - dest);
}
/* INDEX >> */
/* Writing the packet body */
band = res->bands;
for (bandno = 0; !packet_empty && bandno < res->numbands; bandno++, ++band) {
opj_tcd_precinct_t *prc;
/* Skip empty bands */
if (opj_tcd_is_band_empty(band)) {
continue;
}
prc = &band->precincts[precno];
l_nb_blocks = prc->cw * prc->ch;
cblk = prc->cblks.enc;
for (cblkno = 0; cblkno < l_nb_blocks; ++cblkno) {
opj_tcd_layer_t *layer = &cblk->layers[layno];
if (!layer->numpasses) {
++cblk;
continue;
}
if (layer->len > length) {
if (p_t2_mode == FINAL_PASS) {
opj_event_msg(p_manager, EVT_ERROR,
"opj_t2_encode_packet(): only %u bytes remaining in "
"output buffer. %u needed.\n",
length, layer->len);
}
return OPJ_FALSE;
}
memcpy(c, layer->data, layer->len);
cblk->numpasses += layer->numpasses;
c += layer->len;
length -= layer->len;
/* << INDEX */
if (cstr_info && cstr_info->index_write) {
opj_packet_info_t *info_PK = &cstr_info->tile[tileno].packet[cstr_info->packno];
info_PK->disto += layer->disto;
if (cstr_info->D_max < info_PK->disto) {
cstr_info->D_max = info_PK->disto;
}
}
++cblk;
/* INDEX >> */
}
}
assert(c >= dest);
* p_data_written += (OPJ_UINT32)(c - dest);
return OPJ_TRUE;
}
static OPJ_BOOL opj_t2_skip_packet(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info,
opj_event_mgr_t *p_manager)
{
OPJ_BOOL l_read_data;
OPJ_UINT32 l_nb_bytes_read = 0;
OPJ_UINT32 l_nb_total_bytes_read = 0;
*p_data_read = 0;
if (! opj_t2_read_packet_header(p_t2, p_tile, p_tcp, p_pi, &l_read_data, p_src,
&l_nb_bytes_read, p_max_length, p_pack_info, p_manager)) {
return OPJ_FALSE;
}
p_src += l_nb_bytes_read;
l_nb_total_bytes_read += l_nb_bytes_read;
p_max_length -= l_nb_bytes_read;
/* we should read data for the packet */
if (l_read_data) {
l_nb_bytes_read = 0;
if (! opj_t2_skip_packet_data(p_t2, p_tile, p_pi, &l_nb_bytes_read,
p_max_length, p_pack_info, p_manager)) {
return OPJ_FALSE;
}
l_nb_total_bytes_read += l_nb_bytes_read;
}
*p_data_read = l_nb_total_bytes_read;
return OPJ_TRUE;
}
static OPJ_BOOL opj_t2_read_packet_header(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_tcp_t *p_tcp,
opj_pi_iterator_t *p_pi,
OPJ_BOOL * p_is_data_present,
OPJ_BYTE *p_src_data,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *p_pack_info,
opj_event_mgr_t *p_manager)
{
/* loop */
OPJ_UINT32 bandno, cblkno;
OPJ_UINT32 l_nb_code_blocks;
OPJ_UINT32 l_remaining_length;
OPJ_UINT32 l_header_length;
OPJ_UINT32 * l_modified_length_ptr = 00;
OPJ_BYTE *l_current_data = p_src_data;
opj_cp_t *l_cp = p_t2->cp;
opj_bio_t *l_bio = 00; /* BIO component */
opj_tcd_band_t *l_band = 00;
opj_tcd_cblk_dec_t* l_cblk = 00;
opj_tcd_resolution_t* l_res =
&p_tile->comps[p_pi->compno].resolutions[p_pi->resno];
OPJ_BYTE *l_header_data = 00;
OPJ_BYTE **l_header_data_start = 00;
OPJ_UINT32 l_present;
if (p_pi->layno == 0) {
l_band = l_res->bands;
/* reset tagtrees */
for (bandno = 0; bandno < l_res->numbands; ++bandno) {
if (!opj_tcd_is_band_empty(l_band)) {
opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno];
if (!(p_pi->precno < (l_band->precincts_data_size / sizeof(
opj_tcd_precinct_t)))) {
opj_event_msg(p_manager, EVT_ERROR, "Invalid precinct\n");
return OPJ_FALSE;
}
opj_tgt_reset(l_prc->incltree);
opj_tgt_reset(l_prc->imsbtree);
l_cblk = l_prc->cblks.dec;
l_nb_code_blocks = l_prc->cw * l_prc->ch;
for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) {
l_cblk->numsegs = 0;
l_cblk->real_num_segs = 0;
++l_cblk;
}
}
++l_band;
}
}
/* SOP markers */
if (p_tcp->csty & J2K_CP_CSTY_SOP) {
if (p_max_length < 6) {
opj_event_msg(p_manager, EVT_WARNING,
"Not enough space for expected SOP marker\n");
} else if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) {
opj_event_msg(p_manager, EVT_WARNING, "Expected SOP marker\n");
} else {
l_current_data += 6;
}
/** TODO : check the Nsop value */
}
/*
When the marker PPT/PPM is used the packet header are store in PPT/PPM marker
This part deal with this characteristic
step 1: Read packet header in the saved structure
step 2: Return to codestream for decoding
*/
l_bio = opj_bio_create();
if (! l_bio) {
return OPJ_FALSE;
}
if (l_cp->ppm == 1) { /* PPM */
l_header_data_start = &l_cp->ppm_data;
l_header_data = *l_header_data_start;
l_modified_length_ptr = &(l_cp->ppm_len);
} else if (p_tcp->ppt == 1) { /* PPT */
l_header_data_start = &(p_tcp->ppt_data);
l_header_data = *l_header_data_start;
l_modified_length_ptr = &(p_tcp->ppt_len);
} else { /* Normal Case */
l_header_data_start = &(l_current_data);
l_header_data = *l_header_data_start;
l_remaining_length = (OPJ_UINT32)(p_src_data + p_max_length - l_header_data);
l_modified_length_ptr = &(l_remaining_length);
}
opj_bio_init_dec(l_bio, l_header_data, *l_modified_length_ptr);
l_present = opj_bio_read(l_bio, 1);
JAS_FPRINTF(stderr, "present=%d \n", l_present);
if (!l_present) {
/* TODO MSD: no test to control the output of this function*/
opj_bio_inalign(l_bio);
l_header_data += opj_bio_numbytes(l_bio);
opj_bio_destroy(l_bio);
/* EPH markers */
if (p_tcp->csty & J2K_CP_CSTY_EPH) {
if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data -
*l_header_data_start)) < 2U) {
opj_event_msg(p_manager, EVT_WARNING,
"Not enough space for expected EPH marker\n");
} else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) {
opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n");
} else {
l_header_data += 2;
}
}
l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start);
*l_modified_length_ptr -= l_header_length;
*l_header_data_start += l_header_length;
/* << INDEX */
/* End of packet header position. Currently only represents the distance to start of packet
Will be updated later by incrementing with packet start value */
if (p_pack_info) {
p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data);
}
/* INDEX >> */
* p_is_data_present = OPJ_FALSE;
*p_data_read = (OPJ_UINT32)(l_current_data - p_src_data);
return OPJ_TRUE;
}
l_band = l_res->bands;
for (bandno = 0; bandno < l_res->numbands; ++bandno, ++l_band) {
opj_tcd_precinct_t *l_prc = &(l_band->precincts[p_pi->precno]);
if (opj_tcd_is_band_empty(l_band)) {
continue;
}
l_nb_code_blocks = l_prc->cw * l_prc->ch;
l_cblk = l_prc->cblks.dec;
for (cblkno = 0; cblkno < l_nb_code_blocks; cblkno++) {
OPJ_UINT32 l_included, l_increment, l_segno;
OPJ_INT32 n;
/* if cblk not yet included before --> inclusion tagtree */
if (!l_cblk->numsegs) {
l_included = opj_tgt_decode(l_bio, l_prc->incltree, cblkno,
(OPJ_INT32)(p_pi->layno + 1));
/* else one bit */
} else {
l_included = opj_bio_read(l_bio, 1);
}
/* if cblk not included */
if (!l_included) {
l_cblk->numnewpasses = 0;
++l_cblk;
JAS_FPRINTF(stderr, "included=%d \n", l_included);
continue;
}
/* if cblk not yet included --> zero-bitplane tagtree */
if (!l_cblk->numsegs) {
OPJ_UINT32 i = 0;
while (!opj_tgt_decode(l_bio, l_prc->imsbtree, cblkno, (OPJ_INT32)i)) {
++i;
}
l_cblk->Mb = (OPJ_UINT32)l_band->numbps;
l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i;
l_cblk->numlenbits = 3;
}
/* number of coding passes */
l_cblk->numnewpasses = opj_t2_getnumpasses(l_bio);
l_increment = opj_t2_getcommacode(l_bio);
/* length indicator increment */
l_cblk->numlenbits += l_increment;
l_segno = 0;
if (!l_cblk->numsegs) {
if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1)) {
opj_bio_destroy(l_bio);
return OPJ_FALSE;
}
} else {
l_segno = l_cblk->numsegs - 1;
if (l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses) {
++l_segno;
if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) {
opj_bio_destroy(l_bio);
return OPJ_FALSE;
}
}
}
n = (OPJ_INT32)l_cblk->numnewpasses;
if ((p_tcp->tccps[p_pi->compno].cblksty & J2K_CCP_CBLKSTY_HT) != 0)
do {
OPJ_UINT32 bit_number;
l_cblk->segs[l_segno].numnewpasses = l_segno == 0 ? 1 : (OPJ_UINT32)n;
bit_number = l_cblk->numlenbits + opj_uint_floorlog2(
l_cblk->segs[l_segno].numnewpasses);
if (bit_number > 32) {
opj_event_msg(p_manager, EVT_ERROR,
"Invalid bit number %d in opj_t2_read_packet_header()\n",
bit_number);
opj_bio_destroy(l_bio);
return OPJ_FALSE;
}
l_cblk->segs[l_segno].newlen = opj_bio_read(l_bio, bit_number);
JAS_FPRINTF(stderr, "included=%d numnewpasses=%d increment=%d len=%d \n",
l_included, l_cblk->segs[l_segno].numnewpasses, l_increment,
l_cblk->segs[l_segno].newlen);
n -= (OPJ_INT32)l_cblk->segs[l_segno].numnewpasses;
if (n > 0) {
++l_segno;
if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) {
opj_bio_destroy(l_bio);
return OPJ_FALSE;
}
}
} while (n > 0);
else
do {
OPJ_UINT32 bit_number;
l_cblk->segs[l_segno].numnewpasses = (OPJ_UINT32)opj_int_min((OPJ_INT32)(
l_cblk->segs[l_segno].maxpasses - l_cblk->segs[l_segno].numpasses), n);
bit_number = l_cblk->numlenbits + opj_uint_floorlog2(
l_cblk->segs[l_segno].numnewpasses);
if (bit_number > 32) {
opj_event_msg(p_manager, EVT_ERROR,
"Invalid bit number %d in opj_t2_read_packet_header()\n",
bit_number);
opj_bio_destroy(l_bio);
return OPJ_FALSE;
}
l_cblk->segs[l_segno].newlen = opj_bio_read(l_bio, bit_number);
JAS_FPRINTF(stderr, "included=%d numnewpasses=%d increment=%d len=%d \n",
l_included, l_cblk->segs[l_segno].numnewpasses, l_increment,
l_cblk->segs[l_segno].newlen);
n -= (OPJ_INT32)l_cblk->segs[l_segno].numnewpasses;
if (n > 0) {
++l_segno;
if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) {
opj_bio_destroy(l_bio);
return OPJ_FALSE;
}
}
} while (n > 0);
++l_cblk;
}
}
if (!opj_bio_inalign(l_bio)) {
opj_bio_destroy(l_bio);
return OPJ_FALSE;
}
l_header_data += opj_bio_numbytes(l_bio);
opj_bio_destroy(l_bio);
/* EPH markers */
if (p_tcp->csty & J2K_CP_CSTY_EPH) {
if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data -
*l_header_data_start)) < 2U) {
opj_event_msg(p_manager, EVT_WARNING,
"Not enough space for expected EPH marker\n");
} else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) {
opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n");
} else {
l_header_data += 2;
}
}
l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start);
JAS_FPRINTF(stderr, "hdrlen=%d \n", l_header_length);
JAS_FPRINTF(stderr, "packet body\n");
*l_modified_length_ptr -= l_header_length;
*l_header_data_start += l_header_length;
/* << INDEX */
/* End of packet header position. Currently only represents the distance to start of packet
Will be updated later by incrementing with packet start value */
if (p_pack_info) {
p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data);
}
/* INDEX >> */
*p_is_data_present = OPJ_TRUE;
*p_data_read = (OPJ_UINT32)(l_current_data - p_src_data);
return OPJ_TRUE;
}
static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_pi_iterator_t *p_pi,
OPJ_BYTE *p_src_data,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *pack_info,
opj_event_mgr_t* p_manager)
{
OPJ_UINT32 bandno, cblkno;
OPJ_UINT32 l_nb_code_blocks;
OPJ_BYTE *l_current_data = p_src_data;
opj_tcd_band_t *l_band = 00;
opj_tcd_cblk_dec_t* l_cblk = 00;
opj_tcd_resolution_t* l_res =
&p_tile->comps[p_pi->compno].resolutions[p_pi->resno];
OPJ_BOOL partial_buffer = OPJ_FALSE;
OPJ_ARG_NOT_USED(p_t2);
OPJ_ARG_NOT_USED(pack_info);
l_band = l_res->bands;
for (bandno = 0; bandno < l_res->numbands; ++bandno) {
opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno];
if ((l_band->x1 - l_band->x0 == 0) || (l_band->y1 - l_band->y0 == 0)) {
++l_band;
continue;
}
l_nb_code_blocks = l_prc->cw * l_prc->ch;
l_cblk = l_prc->cblks.dec;
for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) {
opj_tcd_seg_t *l_seg = 00;
// if we have a partial data stream, set numchunks to zero
// since we have no data to actually decode.
if (partial_buffer) {
l_cblk->numchunks = 0;
}
if (!l_cblk->numnewpasses) {
/* nothing to do */
++l_cblk;
continue;
}
if (!l_cblk->numsegs) {
l_seg = l_cblk->segs;
++l_cblk->numsegs;
} else {
l_seg = &l_cblk->segs[l_cblk->numsegs - 1];
if (l_seg->numpasses == l_seg->maxpasses) {
++l_seg;
++l_cblk->numsegs;
}
}
do {
/* Check possible overflow (on l_current_data only, assumes input args already checked) then size */
if ((((OPJ_SIZE_T)l_current_data + (OPJ_SIZE_T)l_seg->newlen) <
(OPJ_SIZE_T)l_current_data) ||
(l_current_data + l_seg->newlen > p_src_data + p_max_length) ||
(partial_buffer)) {
if (p_t2->cp->strict) {
opj_event_msg(p_manager, EVT_ERROR,
"read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
return OPJ_FALSE;
} else {
opj_event_msg(p_manager, EVT_WARNING,
"read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
// skip this codeblock since it is a partial read
partial_buffer = OPJ_TRUE;
l_cblk->numchunks = 0;
l_seg->numpasses += l_seg->numnewpasses;
l_cblk->numnewpasses -= l_seg->numnewpasses;
if (l_cblk->numnewpasses > 0) {
++l_seg;
++l_cblk->numsegs;
break;
}
continue;
}
}
#ifdef USE_JPWL
/* we need here a j2k handle to verify if making a check to
the validity of cblocks parameters is selected from user (-W) */
/* let's check that we are not exceeding */
if ((l_cblk->len + l_seg->newlen) > 8192) {
opj_event_msg(p_manager, EVT_WARNING,
"JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
if (!JPWL_ASSUME) {
opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n");
return OPJ_FALSE;
}
l_seg->newlen = 8192 - l_cblk->len;
opj_event_msg(p_manager, EVT_WARNING, " - truncating segment to %d\n",
l_seg->newlen);
break;
};
#endif /* USE_JPWL */
Decoding: do not allocate memory for the codestream of each codeblock Currently we allocate at least 8192 bytes for each codeblock, and copy the relevant parts of the codestream in that per-codeblock buffer as we decode packets. As the whole codestream for the tile is ingested in memory and alive during the decoding, we can directly point to it instead of copying. But to do that, we need an intermediate concept, a 'chunk' of code-stream segment, given that segments may be made of data at different places in the code-stream when quality layers are used. With that change, the decoding of MAPA_005.jp2 goes down from the previous improvement of 2.7 GB down to 1.9 GB. New profile: n4: 1885648469 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E78287: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D7B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E7272C: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 1610689344 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 1610689344 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 1610689344 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BBF0: opj_j2k_read_tile_header (j2k.c:4685) n1: 219232541 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 219232541 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 219232541 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 39822000 0x4E727A9: opj_tcd_init_decode_tile (tcd.c:1219) n1: 39822000 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 39822000 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 39822000 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 39822000 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 39822000 0x40374E: main (opj_decompress.c:1459) n0: 15904584 in 52 places, all below massif's threshold (1.00%)
2017-07-06 16:11:11 +02:00
Slight improvement in management of code block chunks Instead of having the chunk array at the segment level, we can move it down to the codeblock itself since segments are filled in sequential order. Limit the number of memory allocation, and decrease slightly the memory usage. On MAPA_005.jp2 n4: 1871312549 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E781E7: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D1B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E726CF: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 1610689344 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 1610689344 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 1610689344 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BC50: opj_j2k_read_tile_header (j2k.c:4683) n1: 219232541 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 219232541 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 219232541 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 23893200 0x4E72735: opj_tcd_init_decode_tile (tcd.c:1225) n1: 23893200 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 23893200 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 23893200 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 23893200 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 23893200 0x40374E: main (opj_decompress.c:1459) n0: 17497464 in 52 places, all below massif's threshold (1.00%)
2017-07-06 19:34:21 +02:00
if (l_cblk->numchunks == l_cblk->numchunksalloc) {
OPJ_UINT32 l_numchunksalloc = l_cblk->numchunksalloc * 2 + 1;
Decoding: do not allocate memory for the codestream of each codeblock Currently we allocate at least 8192 bytes for each codeblock, and copy the relevant parts of the codestream in that per-codeblock buffer as we decode packets. As the whole codestream for the tile is ingested in memory and alive during the decoding, we can directly point to it instead of copying. But to do that, we need an intermediate concept, a 'chunk' of code-stream segment, given that segments may be made of data at different places in the code-stream when quality layers are used. With that change, the decoding of MAPA_005.jp2 goes down from the previous improvement of 2.7 GB down to 1.9 GB. New profile: n4: 1885648469 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E78287: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D7B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E7272C: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 1610689344 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 1610689344 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 1610689344 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BBF0: opj_j2k_read_tile_header (j2k.c:4685) n1: 219232541 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 219232541 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 219232541 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 39822000 0x4E727A9: opj_tcd_init_decode_tile (tcd.c:1219) n1: 39822000 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 39822000 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 39822000 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 39822000 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 39822000 0x40374E: main (opj_decompress.c:1459) n0: 15904584 in 52 places, all below massif's threshold (1.00%)
2017-07-06 16:11:11 +02:00
opj_tcd_seg_data_chunk_t* l_chunks =
Slight improvement in management of code block chunks Instead of having the chunk array at the segment level, we can move it down to the codeblock itself since segments are filled in sequential order. Limit the number of memory allocation, and decrease slightly the memory usage. On MAPA_005.jp2 n4: 1871312549 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E781E7: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D1B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E726CF: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 1610689344 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 1610689344 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 1610689344 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BC50: opj_j2k_read_tile_header (j2k.c:4683) n1: 219232541 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 219232541 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 219232541 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 23893200 0x4E72735: opj_tcd_init_decode_tile (tcd.c:1225) n1: 23893200 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 23893200 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 23893200 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 23893200 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 23893200 0x40374E: main (opj_decompress.c:1459) n0: 17497464 in 52 places, all below massif's threshold (1.00%)
2017-07-06 19:34:21 +02:00
(opj_tcd_seg_data_chunk_t*)opj_realloc(l_cblk->chunks,
Decoding: do not allocate memory for the codestream of each codeblock Currently we allocate at least 8192 bytes for each codeblock, and copy the relevant parts of the codestream in that per-codeblock buffer as we decode packets. As the whole codestream for the tile is ingested in memory and alive during the decoding, we can directly point to it instead of copying. But to do that, we need an intermediate concept, a 'chunk' of code-stream segment, given that segments may be made of data at different places in the code-stream when quality layers are used. With that change, the decoding of MAPA_005.jp2 goes down from the previous improvement of 2.7 GB down to 1.9 GB. New profile: n4: 1885648469 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E78287: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D7B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E7272C: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 1610689344 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 1610689344 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 1610689344 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BBF0: opj_j2k_read_tile_header (j2k.c:4685) n1: 219232541 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 219232541 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 219232541 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 39822000 0x4E727A9: opj_tcd_init_decode_tile (tcd.c:1219) n1: 39822000 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 39822000 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 39822000 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 39822000 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 39822000 0x40374E: main (opj_decompress.c:1459) n0: 15904584 in 52 places, all below massif's threshold (1.00%)
2017-07-06 16:11:11 +02:00
l_numchunksalloc * sizeof(opj_tcd_seg_data_chunk_t));
if (l_chunks == NULL) {
opj_event_msg(p_manager, EVT_ERROR,
"cannot allocate opj_tcd_seg_data_chunk_t* array");
return OPJ_FALSE;
}
Slight improvement in management of code block chunks Instead of having the chunk array at the segment level, we can move it down to the codeblock itself since segments are filled in sequential order. Limit the number of memory allocation, and decrease slightly the memory usage. On MAPA_005.jp2 n4: 1871312549 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E781E7: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D1B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E726CF: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 1610689344 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 1610689344 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 1610689344 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BC50: opj_j2k_read_tile_header (j2k.c:4683) n1: 219232541 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 219232541 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 219232541 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 23893200 0x4E72735: opj_tcd_init_decode_tile (tcd.c:1225) n1: 23893200 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 23893200 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 23893200 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 23893200 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 23893200 0x40374E: main (opj_decompress.c:1459) n0: 17497464 in 52 places, all below massif's threshold (1.00%)
2017-07-06 19:34:21 +02:00
l_cblk->chunks = l_chunks;
l_cblk->numchunksalloc = l_numchunksalloc;
}
Slight improvement in management of code block chunks Instead of having the chunk array at the segment level, we can move it down to the codeblock itself since segments are filled in sequential order. Limit the number of memory allocation, and decrease slightly the memory usage. On MAPA_005.jp2 n4: 1871312549 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E781E7: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D1B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E726CF: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 1610689344 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 1610689344 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 1610689344 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BC50: opj_j2k_read_tile_header (j2k.c:4683) n1: 219232541 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 219232541 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 219232541 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 23893200 0x4E72735: opj_tcd_init_decode_tile (tcd.c:1225) n1: 23893200 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 23893200 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 23893200 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 23893200 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 23893200 0x40374E: main (opj_decompress.c:1459) n0: 17497464 in 52 places, all below massif's threshold (1.00%)
2017-07-06 19:34:21 +02:00
l_cblk->chunks[l_cblk->numchunks].data = l_current_data;
l_cblk->chunks[l_cblk->numchunks].len = l_seg->newlen;
l_cblk->numchunks ++;
l_current_data += l_seg->newlen;
Slight improvement in management of code block chunks Instead of having the chunk array at the segment level, we can move it down to the codeblock itself since segments are filled in sequential order. Limit the number of memory allocation, and decrease slightly the memory usage. On MAPA_005.jp2 n4: 1871312549 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E781E7: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D1B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E726CF: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 1610689344 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 1610689344 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 1610689344 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BC50: opj_j2k_read_tile_header (j2k.c:4683) n1: 219232541 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 219232541 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 219232541 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 23893200 0x4E72735: opj_tcd_init_decode_tile (tcd.c:1225) n1: 23893200 0x4E4BE39: opj_j2k_read_tile_header (j2k.c:8617) n1: 23893200 0x4E4C902: opj_j2k_decode_tiles (j2k.c:10348) n1: 23893200 0x4E4E3CE: opj_j2k_decode (j2k.c:7846) n1: 23893200 0x4E53002: opj_jp2_decode (jp2.c:1564) n0: 23893200 0x40374E: main (opj_decompress.c:1459) n0: 17497464 in 52 places, all below massif's threshold (1.00%)
2017-07-06 19:34:21 +02:00
l_seg->len += l_seg->newlen;
l_seg->numpasses += l_seg->numnewpasses;
l_cblk->numnewpasses -= l_seg->numnewpasses;
l_seg->real_num_passes = l_seg->numpasses;
if (l_cblk->numnewpasses > 0) {
++l_seg;
++l_cblk->numsegs;
}
} while (l_cblk->numnewpasses > 0);
l_cblk->real_num_segs = l_cblk->numsegs;
++l_cblk;
} /* next code_block */
++l_band;
}
// return the number of bytes read
if (partial_buffer) {
*(p_data_read) = p_max_length;
} else {
*(p_data_read) = (OPJ_UINT32)(l_current_data - p_src_data);
}
return OPJ_TRUE;
}
static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2,
opj_tcd_tile_t *p_tile,
opj_pi_iterator_t *p_pi,
OPJ_UINT32 * p_data_read,
OPJ_UINT32 p_max_length,
opj_packet_info_t *pack_info,
opj_event_mgr_t *p_manager)
{
OPJ_UINT32 bandno, cblkno;
OPJ_UINT32 l_nb_code_blocks;
opj_tcd_band_t *l_band = 00;
opj_tcd_cblk_dec_t* l_cblk = 00;
opj_tcd_resolution_t* l_res =
&p_tile->comps[p_pi->compno].resolutions[p_pi->resno];
OPJ_ARG_NOT_USED(p_t2);
OPJ_ARG_NOT_USED(pack_info);
*p_data_read = 0;
l_band = l_res->bands;
for (bandno = 0; bandno < l_res->numbands; ++bandno) {
opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno];
if ((l_band->x1 - l_band->x0 == 0) || (l_band->y1 - l_band->y0 == 0)) {
++l_band;
continue;
}
l_nb_code_blocks = l_prc->cw * l_prc->ch;
l_cblk = l_prc->cblks.dec;
for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) {
opj_tcd_seg_t *l_seg = 00;
if (!l_cblk->numnewpasses) {
/* nothing to do */
++l_cblk;
continue;
}
if (!l_cblk->numsegs) {
l_seg = l_cblk->segs;
++l_cblk->numsegs;
} else {
l_seg = &l_cblk->segs[l_cblk->numsegs - 1];
if (l_seg->numpasses == l_seg->maxpasses) {
++l_seg;
++l_cblk->numsegs;
}
}
do {
/* Check possible overflow then size */
if (((*p_data_read + l_seg->newlen) < (*p_data_read)) ||
((*p_data_read + l_seg->newlen) > p_max_length)) {
if (p_t2->cp->strict) {
opj_event_msg(p_manager, EVT_ERROR,
"skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
return OPJ_FALSE;
} else {
opj_event_msg(p_manager, EVT_WARNING,
"skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
}
}
#ifdef USE_JPWL
/* we need here a j2k handle to verify if making a check to
the validity of cblocks parameters is selected from user (-W) */
/* let's check that we are not exceeding */
if ((l_cblk->len + l_seg->newlen) > 8192) {
opj_event_msg(p_manager, EVT_WARNING,
"JPWL: segment too long (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
if (!JPWL_ASSUME) {
opj_event_msg(p_manager, EVT_ERROR, "JPWL: giving up\n");
return -999;
}
l_seg->newlen = 8192 - l_cblk->len;
opj_event_msg(p_manager, EVT_WARNING, " - truncating segment to %d\n",
l_seg->newlen);
break;
};
#endif /* USE_JPWL */
JAS_FPRINTF(stderr, "p_data_read (%d) newlen (%d) \n", *p_data_read,
l_seg->newlen);
*(p_data_read) += l_seg->newlen;
l_seg->numpasses += l_seg->numnewpasses;
l_cblk->numnewpasses -= l_seg->numnewpasses;
if (l_cblk->numnewpasses > 0) {
++l_seg;
++l_cblk->numsegs;
}
} while (l_cblk->numnewpasses > 0);
++l_cblk;
}
++l_band;
}
return OPJ_TRUE;
}
static OPJ_BOOL opj_t2_init_seg(opj_tcd_cblk_dec_t* cblk,
OPJ_UINT32 index,
OPJ_UINT32 cblksty,
OPJ_UINT32 first)
{
opj_tcd_seg_t* seg = 00;
OPJ_UINT32 l_nb_segs = index + 1;
if (l_nb_segs > cblk->m_current_max_segs) {
opj_tcd_seg_t* new_segs;
Decoding: do not allocate memory for the codestream of each codeblock Currently we allocate at least 8192 bytes for each codeblock, and copy the relevant parts of the codestream in that per-codeblock buffer as we decode packets. As the whole codestream for the tile is ingested in memory and alive during the decoding, we can directly point to it instead of copying. But to do that, we need an intermediate concept, a 'chunk' of code-stream segment, given that segments may be made of data at different places in the code-stream when quality layers are used. With that change, the decoding of MAPA_005.jp2 goes down from the previous improvement of 2.7 GB down to 1.9 GB. New profile: n4: 1885648469 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E78287: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D7B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E7272C: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 1610689344 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 1610689344 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 1610689344 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BBF0: opj_j2k_read_tile_header (j2k.c:4685) n1: 219232541 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 219232541 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 219232541 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 39822000 0x4E727A9: opj_tcd_init_decode_tile (tcd.c:1219) n1: 39822000 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 39822000 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 39822000 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 39822000 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 39822000 0x40374E: main (opj_decompress.c:1459) n0: 15904584 in 52 places, all below massif's threshold (1.00%)
2017-07-06 16:11:11 +02:00
OPJ_UINT32 l_m_current_max_segs = cblk->m_current_max_segs +
OPJ_J2K_DEFAULT_NB_SEGS;
new_segs = (opj_tcd_seg_t*) opj_realloc(cblk->segs,
Decoding: do not allocate memory for the codestream of each codeblock Currently we allocate at least 8192 bytes for each codeblock, and copy the relevant parts of the codestream in that per-codeblock buffer as we decode packets. As the whole codestream for the tile is ingested in memory and alive during the decoding, we can directly point to it instead of copying. But to do that, we need an intermediate concept, a 'chunk' of code-stream segment, given that segments may be made of data at different places in the code-stream when quality layers are used. With that change, the decoding of MAPA_005.jp2 goes down from the previous improvement of 2.7 GB down to 1.9 GB. New profile: n4: 1885648469 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E78287: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D7B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E7272C: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 1610689344 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 1610689344 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 1610689344 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BBF0: opj_j2k_read_tile_header (j2k.c:4685) n1: 219232541 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 219232541 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 219232541 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 39822000 0x4E727A9: opj_tcd_init_decode_tile (tcd.c:1219) n1: 39822000 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 39822000 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 39822000 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 39822000 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 39822000 0x40374E: main (opj_decompress.c:1459) n0: 15904584 in 52 places, all below massif's threshold (1.00%)
2017-07-06 16:11:11 +02:00
l_m_current_max_segs * sizeof(opj_tcd_seg_t));
if (! new_segs) {
/* opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to initialize segment %d\n", l_nb_segs); */
return OPJ_FALSE;
}
cblk->segs = new_segs;
Decoding: do not allocate memory for the codestream of each codeblock Currently we allocate at least 8192 bytes for each codeblock, and copy the relevant parts of the codestream in that per-codeblock buffer as we decode packets. As the whole codestream for the tile is ingested in memory and alive during the decoding, we can directly point to it instead of copying. But to do that, we need an intermediate concept, a 'chunk' of code-stream segment, given that segments may be made of data at different places in the code-stream when quality layers are used. With that change, the decoding of MAPA_005.jp2 goes down from the previous improvement of 2.7 GB down to 1.9 GB. New profile: n4: 1885648469 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E78287: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D7B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E7272C: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 1610689344 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 1610689344 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 1610689344 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BBF0: opj_j2k_read_tile_header (j2k.c:4685) n1: 219232541 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 219232541 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 219232541 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 39822000 0x4E727A9: opj_tcd_init_decode_tile (tcd.c:1219) n1: 39822000 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 39822000 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 39822000 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 39822000 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 39822000 0x40374E: main (opj_decompress.c:1459) n0: 15904584 in 52 places, all below massif's threshold (1.00%)
2017-07-06 16:11:11 +02:00
memset(new_segs + cblk->m_current_max_segs,
0, OPJ_J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));
cblk->m_current_max_segs = l_m_current_max_segs;
}
seg = &cblk->segs[index];
Decoding: do not allocate memory for the codestream of each codeblock Currently we allocate at least 8192 bytes for each codeblock, and copy the relevant parts of the codestream in that per-codeblock buffer as we decode packets. As the whole codestream for the tile is ingested in memory and alive during the decoding, we can directly point to it instead of copying. But to do that, we need an intermediate concept, a 'chunk' of code-stream segment, given that segments may be made of data at different places in the code-stream when quality layers are used. With that change, the decoding of MAPA_005.jp2 goes down from the previous improvement of 2.7 GB down to 1.9 GB. New profile: n4: 1885648469 (heap allocation functions) malloc/new/new[], --alloc-fns, etc. n1: 1610689344 0x4E78287: opj_aligned_malloc (opj_malloc.c:61) n1: 1610689344 0x4E71D7B: opj_alloc_tile_component_data (tcd.c:676) n1: 1610689344 0x4E7272C: opj_tcd_init_decode_tile (tcd.c:816) n1: 1610689344 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 1610689344 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 1610689344 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 1610689344 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 1610689344 0x40374E: main (opj_decompress.c:1459) n1: 219232541 0x4E4BBF0: opj_j2k_read_tile_header (j2k.c:4685) n1: 219232541 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 219232541 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 219232541 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 219232541 0x40374E: main (opj_decompress.c:1459) n1: 39822000 0x4E727A9: opj_tcd_init_decode_tile (tcd.c:1219) n1: 39822000 0x4E4BDD9: opj_j2k_read_tile_header (j2k.c:8618) n1: 39822000 0x4E4C8A2: opj_j2k_decode_tiles (j2k.c:10349) n1: 39822000 0x4E4E36E: opj_j2k_decode (j2k.c:7847) n1: 39822000 0x4E52FA2: opj_jp2_decode (jp2.c:1564) n0: 39822000 0x40374E: main (opj_decompress.c:1459) n0: 15904584 in 52 places, all below massif's threshold (1.00%)
2017-07-06 16:11:11 +02:00
opj_tcd_reinit_segment(seg);
if (cblksty & J2K_CCP_CBLKSTY_TERMALL) {
seg->maxpasses = 1;
} else if (cblksty & J2K_CCP_CBLKSTY_LAZY) {
if (first) {
seg->maxpasses = 10;
} else {
seg->maxpasses = (((seg - 1)->maxpasses == 1) ||
((seg - 1)->maxpasses == 10)) ? 2 : 1;
}
} else {
/* See paragraph "B.10.6 Number of coding passes" of the standard.
* Probably that 109 must be interpreted a (Mb-1)*3 + 1 with Mb=37,
* Mb being the maximum number of bit-planes available for the
* representation of coefficients in the sub-band */
seg->maxpasses = 109;
}
return OPJ_TRUE;
}