diff --git a/CHANGES b/CHANGES index 68491650..16da7b78 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,9 @@ What's New for OpenJPEG ! : changed + : added +October 21, 2011 +* [mickael] WIP: enhance codestream index generation + October 20, 2011 * [mickael] WIP: isolate dump test suite * [mickael] WIP: remove memory leak about new jp2_read_marker function diff --git a/applications/codec/j2k_to_image.c b/applications/codec/j2k_to_image.c index 3296ec7f..1013ef60 100644 --- a/applications/codec/j2k_to_image.c +++ b/applications/codec/j2k_to_image.c @@ -579,6 +579,7 @@ int main(int argc, char **argv) opj_image_t* image = NULL; opj_stream_t *cio = NULL; /* Stream */ opj_codec_t* dinfo = NULL; /* Handle to a decompressor */ + opj_codestream_index_t* cstr_index = NULL; char indexfilename[OPJ_PATH_LEN]; /* index file name */ @@ -720,6 +721,10 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + opj_dump_codec(dinfo, OPJ_J2K_MH_IND, stdout ); + + cstr_index = opj_get_cstr_index(dinfo); + /* Close the byte stream */ opj_stream_destroy(cio); fclose(fsrc); @@ -819,6 +824,9 @@ int main(int argc, char **argv) /* free image data structure */ opj_image_destroy(image); + /* destroy the codestream index */ + opj_destroy_cstr_index(&cstr_index); + } return EXIT_SUCCESS; } diff --git a/libopenjpeg/j2k.c b/libopenjpeg/j2k.c index 263713b7..37d4693d 100644 --- a/libopenjpeg/j2k.c +++ b/libopenjpeg/j2k.c @@ -123,12 +123,6 @@ static const struct opj_dec_memory_marker_handler * j2k_get_marker_handler (OPJ_ */ static void j2k_tcp_destroy (opj_tcp_v2_t *p_tcp); -/** - * Destroys a codestream index structure. - * - * @param p_cstr_ind the codestream index parameter to destroy. - */ -static void j2k_destroy_cstr_index (opj_codestream_index_t* p_cstr_ind); /** * Destroys a coding parameter structure. @@ -684,6 +678,7 @@ Add tile header marker information */ static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len); +static void j2k_add_tlmarker_v2(OPJ_UINT32 tileno, opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_UINT32 pos, OPJ_UINT32 len); /** * Reads an unknown marker @@ -804,6 +799,8 @@ j2k_prog_order_t j2k_prog_order_list[] = { {(OPJ_PROG_ORDER)-1, ""} }; + + /** * FIXME DOC */ @@ -3707,6 +3704,48 @@ opj_bool j2k_read_sot_v2 ( || (l_tile_y >= p_j2k->m_specific_param.m_decoder.m_end_tile_y); /* Index */ + if (p_j2k->cstr_index) + { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tileno = p_j2k->m_current_tile_number; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno = l_current_part; + + if (l_num_parts != 0){ + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].nb_tps = l_num_parts; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = l_num_parts; + + + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + (opj_tp_index_t*)opj_calloc(l_num_parts, sizeof(opj_tp_index_t)); + else + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + (opj_tp_index_t*)opj_realloc( + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, + l_num_parts* sizeof(opj_tp_index_t)); + } + else{ + /*if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index)*/ { + + if (!p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index) { + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps = 10; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + (opj_tp_index_t*)opj_calloc( p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps, + sizeof(opj_tp_index_t)); + } + + if ( l_current_part >= p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps ){ + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps += 10; + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index = + (opj_tp_index_t*)opj_realloc( p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index, + p_j2k->cstr_index->tile_index[p_j2k->m_current_tile_number].current_nb_tps + * sizeof(opj_tp_index_t)); + } + } + + } + + } + /* FIXME move this onto a separate method to call before reading any SOT, remove part about main_end header, use a index struct inside p_j2k */ /* if (p_j2k->cstr_info) { @@ -3899,17 +3938,31 @@ opj_bool j2k_read_sod_v2 ( return OPJ_FALSE; } -#ifdef TODO_MSD /* FIXME */ - l_cstr_index = p_j2k->cstr_index; /* Index */ + l_cstr_index = p_j2k->cstr_index; if (l_cstr_index) { - OPJ_SIZE_T l_current_pos = opj_stream_tell(p_stream)-1; - l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[p_j2k->m_specific_param.m_encoder.m_current_tile_part_number].tp_end_header = l_current_pos; + OPJ_SIZE_T l_current_pos = opj_stream_tell(p_stream) - 2; + OPJ_UINT32 l_current_tile_part =l_cstr_index->tile_index[p_j2k->m_current_tile_number].current_tpsno; + l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_header = + l_current_pos; + l_cstr_index->tile_index[p_j2k->m_current_tile_number].tp_index[l_current_tile_part].end_pos = + l_current_pos + p_j2k->m_specific_param.m_decoder.m_sot_length + 2; - l_cstr_index->packno = 0; + j2k_add_tlmarker_v2(p_j2k->m_current_tile_number, + l_cstr_index, + J2K_MS_SOD, + l_current_pos, + p_j2k->m_specific_param.m_decoder.m_sot_length + 2); + + /*l_cstr_index->packno = 0;*/ } -#endif + + + + + + l_current_read_size = opj_stream_read_data( p_stream, *l_current_data + *l_tile_len, @@ -5763,6 +5816,38 @@ static void j2k_add_tlmarker( int tileno, opj_codestream_info_t *cstr_info, unsi cstr_info->tile[tileno].marknum++; } +static void j2k_add_tlmarker_v2(OPJ_UINT32 tileno, opj_codestream_index_t *cstr_index, OPJ_UINT32 type, OPJ_UINT32 pos, OPJ_UINT32 len) +{ + + if (!cstr_index) + return; + + if (!cstr_index->tile_index) + + /* expand the list? */ + if ((cstr_index->tile_index[tileno].marknum + 1) > cstr_index->tile_index[tileno].maxmarknum) { + cstr_index->tile_index[tileno].maxmarknum = 100 + (int) ((float) cstr_index->tile_index[tileno].maxmarknum * 1.0F); + cstr_index->tile_index[tileno].marker = + (opj_marker_info_t*)opj_realloc(cstr_index->tile_index[tileno].marker, + cstr_index->tile_index[tileno].maxmarknum *sizeof(opj_marker_info_t)); + } + + /* add the marker */ + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].type = (OPJ_UINT16)type; + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].pos = (OPJ_INT32)pos; + cstr_index->tile_index[tileno].marker[cstr_index->tile_index[tileno].marknum].len = (OPJ_INT32)len; + cstr_index->tile_index[tileno].marknum++; + + if (type == J2K_MS_SOT) { + OPJ_UINT32 l_current_tile_part = cstr_index->tile_index[tileno].current_tpsno; + + if (cstr_index->tile_index[tileno].tp_index) + cstr_index->tile_index[tileno].tp_index[l_current_tile_part].start_pos = pos; + + } + +} + @@ -6357,7 +6442,29 @@ void j2k_destroy_cstr_index (opj_codestream_index_t *p_cstr_ind) } if (p_cstr_ind->tile_index) { - // FIXME not used for the moment + OPJ_UINT32 it_tile = 0; + + for (it_tile=0; it_tile < p_cstr_ind->nb_of_tiles; it_tile++) { + + if(p_cstr_ind->tile_index[it_tile].packet_index) { + opj_free(p_cstr_ind->tile_index[it_tile].packet_index); + p_cstr_ind->tile_index[it_tile].packet_index = NULL; + } + + if(p_cstr_ind->tile_index[it_tile].tp_index){ + opj_free(p_cstr_ind->tile_index[it_tile].tp_index); + p_cstr_ind->tile_index[it_tile].tp_index = NULL; + } + + if(p_cstr_ind->tile_index[it_tile].marker){ + opj_free(p_cstr_ind->tile_index[it_tile].marker); + p_cstr_ind->tile_index[it_tile].marker = NULL; + + } + } + + opj_free( p_cstr_ind->tile_index); + p_cstr_ind->tile_index = NULL; } opj_free(p_cstr_ind); @@ -6579,6 +6686,16 @@ opj_bool j2k_read_tile_header( opj_j2k_v2_t * p_j2k, return OPJ_FALSE; } +/* if (l_current_marker == J2K_MS_SOT) + j2k_add_tlmarker();*/ + + /* Add the marker to the codestream index*/ + j2k_add_tlmarker_v2(p_j2k->m_current_tile_number, + p_j2k->cstr_index, + l_marker_handler->id, + (OPJ_UINT32) opj_stream_tell(p_stream) - l_marker_size - 4, + l_marker_size + 4 ); + if (p_j2k->m_specific_param.m_decoder.m_skip_data) { /* Skip the rest of the tile part header*/ if (opj_stream_skip(p_stream,p_j2k->m_specific_param.m_decoder.m_sot_length,p_manager) != p_j2k->m_specific_param.m_decoder.m_sot_length) { @@ -6605,6 +6722,8 @@ opj_bool j2k_read_tile_header( opj_j2k_v2_t * p_j2k, return OPJ_FALSE; } + + if (! p_j2k->m_specific_param.m_decoder.m_can_decode){ /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */ if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) { @@ -7426,7 +7545,7 @@ void j2k_dump (opj_j2k_v2_t* p_j2k, OPJ_INT32 flag, FILE* out_stream) void j2k_dump_MH_index(opj_j2k_v2_t* p_j2k, FILE* out_stream) { opj_codestream_index_t* cstr_index = p_j2k->cstr_index; - OPJ_UINT32 it_marker; + OPJ_UINT32 it_marker, it_tile, it_tile_part; fprintf(out_stream, "Codestream index from main header: {\n"); @@ -7435,14 +7554,49 @@ void j2k_dump_MH_index(opj_j2k_v2_t* p_j2k, FILE* out_stream) fprintf(out_stream, "\t Marker list: {\n"); - for (it_marker=0; it_marker < cstr_index->marknum ; it_marker++){ - fprintf(out_stream, "\t\t type=%#x, pos=%d, len=%d\n", - cstr_index->marker[it_marker].type, - cstr_index->marker[it_marker].pos, - cstr_index->marker[it_marker].len ); + if (cstr_index->marker){ + for (it_marker=0; it_marker < cstr_index->marknum ; it_marker++){ + fprintf(out_stream, "\t\t type=%#x, pos=%d, len=%d\n", + cstr_index->marker[it_marker].type, + cstr_index->marker[it_marker].pos, + cstr_index->marker[it_marker].len ); + } } - fprintf(out_stream, "\t }\n}\n"); + fprintf(out_stream, "\t }\n"); + + + if (cstr_index->tile_index){ + fprintf(out_stream, "\t Tile index: {\n"); + + for (it_tile=0; it_tile < cstr_index->nb_of_tiles ; it_tile++){ + OPJ_UINT32 nb_of_tile_part = cstr_index->tile_index[it_tile].nb_tps; + + fprintf(out_stream, "\t\t nb of tile-part in tile [%d]=%d\n", it_tile, nb_of_tile_part); + + if (cstr_index->tile_index[it_tile].tp_index){ + for (it_tile_part =0; it_tile_part < nb_of_tile_part; it_tile_part++){ + fprintf(out_stream, "\t\t\t tile-part[%d]: star_pos=%d, end_header=%d, end_pos=%d.\n", + it_tile_part, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].start_pos, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_header, + cstr_index->tile_index[it_tile].tp_index[it_tile_part].end_pos); + } + } + + if (cstr_index->tile_index[it_tile].marker){ + for (it_marker=0; it_marker < cstr_index->tile_index[it_tile].marknum ; it_marker++){ + fprintf(out_stream, "\t\t type=%#x, pos=%d, len=%d\n", + cstr_index->tile_index[it_tile].marker[it_marker].type, + cstr_index->tile_index[it_tile].marker[it_marker].pos, + cstr_index->tile_index[it_tile].marker[it_marker].len ); + } + } + } + fprintf(out_stream,"\t }\n"); + } + + fprintf(out_stream,"}\n"); } @@ -7671,20 +7825,124 @@ opj_codestream_index_t* j2k_get_cstr_index(opj_j2k_v2_t* p_j2k) l_cstr_index->main_head_end = p_j2k->cstr_index->main_head_end; l_cstr_index->codestream_size = p_j2k->cstr_index->codestream_size; - l_cstr_index->maxmarknum = p_j2k->cstr_index->maxmarknum; l_cstr_index->marknum = p_j2k->cstr_index->marknum; l_cstr_index->marker = (opj_marker_info_t*)opj_malloc(l_cstr_index->marknum*sizeof(opj_marker_info_t)); - if (!l_cstr_index->marker) + if (!l_cstr_index->marker){ + opj_free( l_cstr_index); return NULL; + } - memcpy(l_cstr_index->marker, p_j2k->cstr_index->marker, l_cstr_index->marknum * sizeof(opj_marker_info_t) ); + if (p_j2k->cstr_index->marker) + memcpy(l_cstr_index->marker, p_j2k->cstr_index->marker, l_cstr_index->marknum * sizeof(opj_marker_info_t) ); + else{ + opj_free(l_cstr_index->marker); + l_cstr_index->marker = NULL; + } - l_cstr_index->tile_index = NULL; /* FIXME not used for the moment*/ + l_cstr_index->nb_of_tiles = p_j2k->cstr_index->nb_of_tiles; + l_cstr_index->tile_index = (opj_tile_index_t*)opj_calloc(l_cstr_index->nb_of_tiles, sizeof(opj_tile_index_t) ); + if (!l_cstr_index->tile_index){ + opj_free( l_cstr_index->marker); + opj_free( l_cstr_index); + return NULL; + } + + if (!p_j2k->cstr_index->tile_index){ + opj_free(l_cstr_index->tile_index); + l_cstr_index->tile_index = NULL; + } + else { + OPJ_UINT32 it_tile = 0; + for (it_tile = 0; it_tile < l_cstr_index->nb_of_tiles; it_tile++ ){ + + /* Tile Marker*/ + l_cstr_index->tile_index[it_tile].marknum = p_j2k->cstr_index->tile_index[it_tile].marknum; + + l_cstr_index->tile_index[it_tile].marker = + (opj_marker_info_t*)opj_malloc(l_cstr_index->tile_index[it_tile].marknum*sizeof(opj_marker_info_t)); + + if (!l_cstr_index->tile_index[it_tile].marker) { + OPJ_UINT32 it_tile_free; + + for (it_tile_free=0; it_tile_free < it_tile; it_tile_free++){ + opj_free(l_cstr_index->tile_index[it_tile_free].marker); + } + + opj_free( l_cstr_index->tile_index); + opj_free( l_cstr_index->marker); + opj_free( l_cstr_index); + return NULL; + } + + if (p_j2k->cstr_index->tile_index[it_tile].marker) + memcpy( l_cstr_index->tile_index[it_tile].marker, + p_j2k->cstr_index->tile_index[it_tile].marker, + l_cstr_index->tile_index[it_tile].marknum * sizeof(opj_marker_info_t) ); + else{ + opj_free(l_cstr_index->tile_index[it_tile].marker); + l_cstr_index->tile_index[it_tile].marker = NULL; + } + + /* Tile part index*/ + l_cstr_index->tile_index[it_tile].nb_tps = p_j2k->cstr_index->tile_index[it_tile].nb_tps; + + l_cstr_index->tile_index[it_tile].tp_index = + (opj_tp_index_t*)opj_malloc(l_cstr_index->tile_index[it_tile].nb_tps*sizeof(opj_tp_index_t)); + + if(!l_cstr_index->tile_index[it_tile].tp_index){ + OPJ_UINT32 it_tile_free; + + for (it_tile_free=0; it_tile_free < it_tile; it_tile_free++){ + opj_free(l_cstr_index->tile_index[it_tile_free].marker); + opj_free(l_cstr_index->tile_index[it_tile_free].tp_index); + } + + opj_free( l_cstr_index->tile_index); + opj_free( l_cstr_index->marker); + opj_free( l_cstr_index); + return NULL; + } + + if (p_j2k->cstr_index->tile_index[it_tile].tp_index){ + memcpy( l_cstr_index->tile_index[it_tile].tp_index, + p_j2k->cstr_index->tile_index[it_tile].tp_index, + l_cstr_index->tile_index[it_tile].nb_tps * sizeof(opj_tp_index_t) ); + } + else{ + opj_free(l_cstr_index->tile_index[it_tile].tp_index); + l_cstr_index->tile_index[it_tile].tp_index = NULL; + } + + /* Packet index (NOT USED)*/ + l_cstr_index->tile_index[it_tile].nb_packet = 0; + l_cstr_index->tile_index[it_tile].packet_index = NULL; + + } + } return l_cstr_index; } +opj_bool j2k_allocate_tile_element_cstr_index(opj_j2k_v2_t *p_j2k) +{ + OPJ_UINT32 it_tile=0; + p_j2k->cstr_index->nb_of_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.tw; + p_j2k->cstr_index->tile_index = (opj_tile_index_t*)opj_calloc(p_j2k->cstr_index->nb_of_tiles, sizeof(opj_tile_index_t)); + if (!p_j2k->cstr_index->tile_index) + return OPJ_FALSE; + + for (it_tile=0; it_tile < p_j2k->cstr_index->nb_of_tiles; it_tile++){ + p_j2k->cstr_index->tile_index[it_tile].maxmarknum = 100; + p_j2k->cstr_index->tile_index[it_tile].marknum = 0; + p_j2k->cstr_index->tile_index[it_tile].marker = (opj_marker_info_t*) + opj_calloc(p_j2k->cstr_index->tile_index[it_tile].maxmarknum, sizeof(opj_marker_info_t)); + if (!p_j2k->cstr_index->tile_index[it_tile].marker) + return OPJ_FALSE; + } + + return OPJ_TRUE; +} /** * Reads the tiles. @@ -7706,6 +7964,12 @@ opj_bool j2k_decode_tiles ( opj_j2k_v2_t *p_j2k, } l_max_data_size = 1000; + /*Allocate and initialize some elements of codestrem index*/ + if (!j2k_allocate_tile_element_cstr_index(p_j2k)) + return OPJ_FALSE; + + + while (OPJ_TRUE) { if (! j2k_read_tile_header( p_j2k, &l_current_tile_no, diff --git a/libopenjpeg/j2k.h b/libopenjpeg/j2k.h index 5ff07f5e..23a6b115 100644 --- a/libopenjpeg/j2k.h +++ b/libopenjpeg/j2k.h @@ -910,6 +910,13 @@ opj_bool j2k_read_header( struct opj_stream_private *p_stream, */ void j2k_destroy (opj_j2k_v2_t *p_j2k); +/** + * Destroys a codestream index structure. + * + * @param p_cstr_ind the codestream index parameter to destroy. + */ +void j2k_destroy_cstr_index (opj_codestream_index_t *p_cstr_ind); + /** * Decode tile data. * @param p_j2k the jpeg2000 codec. diff --git a/libopenjpeg/openjpeg.c b/libopenjpeg/openjpeg.c index e43707f2..9706ff14 100644 --- a/libopenjpeg/openjpeg.c +++ b/libopenjpeg/openjpeg.c @@ -945,18 +945,8 @@ void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t **p_cstr_index) { if (*p_cstr_index){ - if((*p_cstr_index)->marker){ - opj_free((*p_cstr_index)->marker); - (*p_cstr_index)->marker = NULL; - } - - if((*p_cstr_index)->tile_index) { - /* FIXME not used for the moment*/ - } - - opj_free((*p_cstr_index)); + j2k_destroy_cstr_index(*p_cstr_index); (*p_cstr_index) = NULL; - } } diff --git a/libopenjpeg/openjpeg.h b/libopenjpeg/openjpeg.h index 0c59889c..a6aa401c 100644 --- a/libopenjpeg/openjpeg.h +++ b/libopenjpeg/openjpeg.h @@ -873,24 +873,50 @@ typedef struct opj_codestream_info_v2 { } opj_codestream_info_v2_t; + +/** + * Index structure about a tile part + */ +typedef struct opj_tp_index { + /** start position */ + OPJ_UINT32 start_pos; + /** end position of the header */ + OPJ_UINT32 end_header; + /** end position */ + OPJ_UINT32 end_pos; + + + + +} opj_tp_index_t; + /** * Index structure about a tile */ typedef struct opj_tile_index { - /** number (index) of tile */ - int tileno; - /** start position */ - int start_pos; - /** end position of the header */ - int end_header; - /** end position */ - int end_pos; + /** tile index */ + OPJ_UINT32 tileno; /** number of tile parts */ - int num_tps; + OPJ_UINT32 nb_tps; + /** current nb of tile part (allocated)*/ + OPJ_UINT32 current_nb_tps; + /** current tile-part index */ + OPJ_UINT32 current_tpsno; /** information concerning tile parts */ - opj_tp_info_t *tp_index; + opj_tp_index_t *tp_index; + /* UniPG>> */ + /** number of markers */ + OPJ_UINT32 marknum; + /** list of markers */ + opj_marker_info_t *marker; + /** actual size of markers array */ + OPJ_UINT32 maxmarknum; + /* <> */ /** number of markers */ - int marknum; + OPJ_UINT32 marknum; /** list of markers */ opj_marker_info_t *marker; /** actual size of markers array */ - int maxmarknum; + OPJ_UINT32 maxmarknum; /* <