0. support for memory mapped files
1. zero copy reads for buffer/memory mapped stream interface 2. no code block allocation
This commit is contained in:
parent
51efe91971
commit
964b065cf2
|
@ -1177,6 +1177,7 @@ static opj_image_t* upsample_image_components(opj_image_t* original)
|
|||
* OPJ_DECOMPRESS MAIN
|
||||
*/
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
opj_decompress_parameters parameters; /* decompression parameters */
|
||||
|
@ -1236,22 +1237,47 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
/*Decoding image one by one*/
|
||||
for(imageno = 0; imageno < num_images ; imageno++) {
|
||||
for (imageno = 0; imageno < num_images; imageno++) {
|
||||
|
||||
fprintf(stderr,"\n");
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
if(img_fol.set_imgdir==1){
|
||||
if (get_next_file(imageno, dirptr,&img_fol, ¶meters)) {
|
||||
fprintf(stderr,"skipping file...\n");
|
||||
if (img_fol.set_imgdir == 1) {
|
||||
if (get_next_file(imageno, dirptr, &img_fol, ¶meters)) {
|
||||
fprintf(stderr, "skipping file...\n");
|
||||
destroy_parameters(¶meters);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* read the input file and put it in memory */
|
||||
/* ---------------------------------------- */
|
||||
/* DEBUGGING: read the input file and put it in memory */
|
||||
/* --------------------------------------------------- */
|
||||
/*
|
||||
OPJ_BOOL debug_buffers = OPJ_FALSE;
|
||||
if (debug_buffers) {
|
||||
FILE* p_file = NULL;
|
||||
OPJ_SIZE_T sz = 0;
|
||||
OPJ_BYTE* buffer = NULL;
|
||||
|
||||
p_file = fopen(parameters.infile, "rb");
|
||||
if (p_file) {
|
||||
fseek(p_file, 0L, SEEK_END);
|
||||
sz = ftell(p_file);
|
||||
fseek(p_file, 0L, SEEK_SET);
|
||||
buffer = (OPJ_BYTE*)malloc(sz);
|
||||
if (buffer) {
|
||||
OPJ_SIZE_T res = fread(buffer, 1, sz, p_file);
|
||||
if (res) {
|
||||
fclose(p_file);
|
||||
l_stream = opj_stream_create_buffer_stream(buffer, sz, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (!l_stream) {
|
||||
l_stream = opj_stream_create_mapped_file_read_stream(parameters.infile);
|
||||
}
|
||||
|
||||
l_stream = opj_stream_create_default_file_stream(parameters.infile,1);
|
||||
if (!l_stream){
|
||||
fprintf(stderr, "ERROR -> failed to create the stream from the file %s\n", parameters.infile);
|
||||
destroy_parameters(¶meters);
|
||||
|
@ -1284,6 +1310,7 @@ int main(int argc, char **argv)
|
|||
fprintf(stderr, "skipping file..\n");
|
||||
destroy_parameters(¶meters);
|
||||
opj_stream_destroy(l_stream);
|
||||
l_stream = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1363,6 +1390,7 @@ int main(int argc, char **argv)
|
|||
|
||||
/* Close the byte stream */
|
||||
opj_stream_destroy(l_stream);
|
||||
l_stream = NULL;
|
||||
|
||||
if( image->color_space != OPJ_CLRSPC_SYCC
|
||||
&& image->numcomps == 3 && image->comps[0].dx == image->comps[0].dy
|
||||
|
|
|
@ -37,6 +37,8 @@ set(OPENJPEG_SRCS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/pi.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/raw.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/raw.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/segmented_stream.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/segmented_stream.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/t1.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/t1.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/t2.c
|
||||
|
@ -53,6 +55,8 @@ set(OPENJPEG_SRCS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/opj_malloc.c
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/opj_malloc.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/opj_stdint.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vector.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/vector.c
|
||||
)
|
||||
if(BUILD_JPIP)
|
||||
add_definitions(-DUSE_JPIP)
|
||||
|
|
|
@ -156,15 +156,16 @@ opj_stream_t* OPJ_CALLCONV opj_stream_create(OPJ_SIZE_T p_buffer_size,OPJ_BOOL l
|
|||
return 00;
|
||||
}
|
||||
|
||||
l_stream->m_buffer_size = p_buffer_size;
|
||||
l_stream->m_stored_data = (OPJ_BYTE *) opj_malloc(p_buffer_size);
|
||||
if (! l_stream->m_stored_data) {
|
||||
opj_free(l_stream);
|
||||
return 00;
|
||||
if (p_buffer_size) {
|
||||
l_stream->m_buffer_size = p_buffer_size;
|
||||
l_stream->m_stored_data = (OPJ_BYTE *)opj_malloc(p_buffer_size);
|
||||
if (!l_stream->m_stored_data) {
|
||||
opj_free(l_stream);
|
||||
return 00;
|
||||
}
|
||||
l_stream->m_current_data = l_stream->m_stored_data;
|
||||
}
|
||||
|
||||
l_stream->m_current_data = l_stream->m_stored_data;
|
||||
|
||||
if (l_is_input) {
|
||||
l_stream->m_status |= OPJ_STREAM_STATUS_INPUT;
|
||||
l_stream->m_opj_skip = opj_stream_read_skip;
|
||||
|
@ -197,8 +198,10 @@ void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream)
|
|||
if (l_stream->m_free_user_data_fn) {
|
||||
l_stream->m_free_user_data_fn(l_stream->m_user_data);
|
||||
}
|
||||
opj_free(l_stream->m_stored_data);
|
||||
l_stream->m_stored_data = 00;
|
||||
if (l_stream->m_stored_data) {
|
||||
opj_free(l_stream->m_stored_data);
|
||||
l_stream->m_stored_data = 00;
|
||||
}
|
||||
opj_free(l_stream);
|
||||
}
|
||||
}
|
||||
|
@ -214,6 +217,17 @@ void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_strea
|
|||
l_stream->m_read_fn = p_function;
|
||||
}
|
||||
|
||||
void OPJ_CALLCONV opj_stream_set_zero_copy_read_function(opj_stream_t* p_stream, opj_stream_zero_copy_read_fn p_function)
|
||||
{
|
||||
opj_stream_private_t* l_stream = (opj_stream_private_t*)p_stream;
|
||||
|
||||
if ((!l_stream) || (!(l_stream->m_status & OPJ_STREAM_STATUS_INPUT))) {
|
||||
return;
|
||||
}
|
||||
|
||||
l_stream->m_zero_copy_read_fn = p_function;
|
||||
}
|
||||
|
||||
void OPJ_CALLCONV opj_stream_set_seek_function(opj_stream_t* p_stream, opj_stream_seek_fn p_function)
|
||||
{
|
||||
opj_stream_private_t* l_stream = (opj_stream_private_t*) p_stream;
|
||||
|
@ -263,6 +277,12 @@ void OPJ_CALLCONV opj_stream_set_user_data_length(opj_stream_t* p_stream, OPJ_UI
|
|||
l_stream->m_user_data_length = data_length;
|
||||
}
|
||||
|
||||
|
||||
|
||||
OPJ_BOOL opj_stream_supports_zero_copy_read(opj_stream_private_t * p_stream) {
|
||||
return p_stream->m_zero_copy_read_fn ? OPJ_TRUE : OPJ_FALSE;
|
||||
}
|
||||
|
||||
OPJ_SIZE_T opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
|
||||
{
|
||||
OPJ_SIZE_T l_read_nb_bytes = 0;
|
||||
|
@ -370,6 +390,26 @@ OPJ_SIZE_T opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_bu
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
OPJ_SIZE_T opj_stream_read_data_zero_copy(opj_stream_private_t * p_stream, OPJ_BYTE ** p_buffer, OPJ_SIZE_T p_size, opj_event_mgr_t * p_event_mgr)
|
||||
{
|
||||
OPJ_SIZE_T l_read_nb_bytes = p_stream->m_zero_copy_read_fn(p_buffer, p_size, p_stream->m_user_data);
|
||||
|
||||
if (l_read_nb_bytes == (OPJ_SIZE_T)-1) {
|
||||
/* end of stream */
|
||||
opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n");
|
||||
p_stream->m_status |= OPJ_STREAM_STATUS_END;
|
||||
return (OPJ_SIZE_T)-1;
|
||||
}
|
||||
else {
|
||||
p_stream->m_byte_offset += (OPJ_OFF_T)l_read_nb_bytes;
|
||||
return l_read_nb_bytes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
OPJ_SIZE_T opj_stream_write_data (opj_stream_private_t * p_stream,
|
||||
const OPJ_BYTE * p_buffer,
|
||||
OPJ_SIZE_T p_size,
|
||||
|
|
|
@ -98,10 +98,16 @@ typedef struct opj_stream_private
|
|||
OPJ_UINT64 m_user_data_length;
|
||||
|
||||
/**
|
||||
* Pointer to actual read function (NULL at the initialization of the cio.
|
||||
* Pointer to actual read function (NULL at the initialization of the cio).
|
||||
*/
|
||||
opj_stream_read_fn m_read_fn;
|
||||
|
||||
/**
|
||||
* Pointer to actual zero copy read function (NULL at the initialization of the cio).
|
||||
*/
|
||||
opj_stream_zero_copy_read_fn m_zero_copy_read_fn;
|
||||
|
||||
|
||||
/**
|
||||
* Pointer to actual write function (NULL at the initialization of the cio.
|
||||
*/
|
||||
|
@ -268,6 +274,13 @@ void opj_write_float_BE(OPJ_BYTE * p_buffer, OPJ_FLOAT32 p_value);
|
|||
*/
|
||||
OPJ_SIZE_T opj_stream_read_data (opj_stream_private_t * p_stream,OPJ_BYTE * p_buffer, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
|
||||
|
||||
OPJ_SIZE_T opj_stream_read_data_zero_copy(opj_stream_private_t * p_stream, OPJ_BYTE ** p_buffer, OPJ_SIZE_T p_size, struct opj_event_mgr * p_event_mgr);
|
||||
|
||||
/**
|
||||
* Check if this stream supports zero copy reads
|
||||
*/
|
||||
OPJ_BOOL opj_stream_supports_zero_copy_read(opj_stream_private_t * p_stream);
|
||||
|
||||
/**
|
||||
* Writes some bytes to the stream.
|
||||
* @param p_stream the stream to write data to.
|
||||
|
|
|
@ -4310,9 +4310,7 @@ static OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k,
|
|||
{
|
||||
OPJ_SIZE_T l_current_read_size;
|
||||
opj_codestream_index_t * l_cstr_index = 00;
|
||||
OPJ_BYTE ** l_current_data = 00;
|
||||
opj_tcp_t * l_tcp = 00;
|
||||
OPJ_UINT32 * l_tile_len = 00;
|
||||
OPJ_BOOL l_sot_length_pb_detected = OPJ_FALSE;
|
||||
|
||||
/* preconditions */
|
||||
|
@ -4338,8 +4336,6 @@ static OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k,
|
|||
}
|
||||
}
|
||||
|
||||
l_current_data = &(l_tcp->m_data);
|
||||
l_tile_len = &l_tcp->m_data_size;
|
||||
|
||||
/* Patch to support new PHR data */
|
||||
if (p_j2k->m_specific_param.m_decoder.m_sot_length) {
|
||||
|
@ -4349,28 +4345,6 @@ static OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k,
|
|||
opj_event_msg(p_manager, EVT_ERROR, "Tile part length size inconsistent with stream length\n");
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
if (! *l_current_data) {
|
||||
/* LH: oddly enough, in this path, l_tile_len!=0.
|
||||
* TODO: If this was consistent, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...).
|
||||
*/
|
||||
*l_current_data = (OPJ_BYTE*) opj_malloc(p_j2k->m_specific_param.m_decoder.m_sot_length);
|
||||
}
|
||||
else {
|
||||
OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(*l_current_data, *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length);
|
||||
if (! l_new_current_data) {
|
||||
opj_free(*l_current_data);
|
||||
/*nothing more is done as l_current_data will be set to null, and just
|
||||
afterward we enter in the error path
|
||||
and the actual tile_len is updated (committed) at the end of the
|
||||
function. */
|
||||
}
|
||||
*l_current_data = l_new_current_data;
|
||||
}
|
||||
|
||||
if (*l_current_data == 00) {
|
||||
opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tile\n");
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
l_sot_length_pb_detected = OPJ_TRUE;
|
||||
|
@ -4401,11 +4375,24 @@ static OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k,
|
|||
|
||||
/* Patch to support new PHR data */
|
||||
if (!l_sot_length_pb_detected) {
|
||||
l_current_read_size = opj_stream_read_data(
|
||||
p_stream,
|
||||
*l_current_data + *l_tile_len,
|
||||
p_j2k->m_specific_param.m_decoder.m_sot_length,
|
||||
p_manager);
|
||||
if (opj_stream_supports_zero_copy_read(p_stream)) {
|
||||
OPJ_BYTE* ptr = NULL;
|
||||
l_current_read_size = opj_stream_read_data_zero_copy(p_stream,
|
||||
&ptr,
|
||||
p_j2k->m_specific_param.m_decoder.m_sot_length,
|
||||
p_manager);
|
||||
opj_seg_buf_push_back(&l_tcp->m_data, ptr, p_j2k->m_specific_param.m_decoder.m_sot_length);
|
||||
|
||||
}
|
||||
else {
|
||||
opj_seg_buf_alloc_and_push_back(&l_tcp->m_data, p_j2k->m_specific_param.m_decoder.m_sot_length);
|
||||
l_current_read_size = opj_stream_read_data(
|
||||
p_stream,
|
||||
opj_seg_buf_get_global_ptr(&l_tcp->m_data),
|
||||
p_j2k->m_specific_param.m_decoder.m_sot_length,
|
||||
p_manager);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4418,9 +4405,6 @@ static OPJ_BOOL opj_j2k_read_sod (opj_j2k_t *p_j2k,
|
|||
else {
|
||||
p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
|
||||
}
|
||||
|
||||
*l_tile_len += (OPJ_UINT32)l_current_read_size;
|
||||
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
|
@ -7618,11 +7602,7 @@ static void opj_j2k_tcp_destroy (opj_tcp_t *p_tcp)
|
|||
|
||||
static void opj_j2k_tcp_data_destroy (opj_tcp_t *p_tcp)
|
||||
{
|
||||
if (p_tcp->m_data) {
|
||||
opj_free(p_tcp->m_data);
|
||||
p_tcp->m_data = NULL;
|
||||
p_tcp->m_data_size = 0;
|
||||
}
|
||||
opj_seg_buf_cleanup(&p_tcp->m_data);
|
||||
}
|
||||
|
||||
static void opj_j2k_cp_destroy (opj_cp_t *p_cp)
|
||||
|
@ -8002,7 +7982,7 @@ OPJ_BOOL opj_j2k_read_tile_header( opj_j2k_t * p_j2k,
|
|||
OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.th * p_j2k->m_cp.tw;
|
||||
l_tcp = p_j2k->m_cp.tcps + p_j2k->m_current_tile_number;
|
||||
|
||||
while( (p_j2k->m_current_tile_number < l_nb_tiles) && (l_tcp->m_data == 00) ) {
|
||||
while( (p_j2k->m_current_tile_number < l_nb_tiles) && (l_tcp->m_data.segments.data == 00) ) {
|
||||
++p_j2k->m_current_tile_number;
|
||||
++l_tcp;
|
||||
}
|
||||
|
@ -8062,16 +8042,15 @@ OPJ_BOOL opj_j2k_decode_tile ( opj_j2k_t * p_j2k,
|
|||
}
|
||||
|
||||
l_tcp = &(p_j2k->m_cp.tcps[p_tile_index]);
|
||||
if (! l_tcp->m_data) {
|
||||
if (! l_tcp->m_data.segments.data) {
|
||||
opj_j2k_tcp_destroy(l_tcp);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
if (! opj_tcd_decode_tile( p_j2k->m_tcd,
|
||||
l_tcp->m_data,
|
||||
l_tcp->m_data_size,
|
||||
p_tile_index,
|
||||
p_j2k->cstr_index, p_manager) ) {
|
||||
if (! opj_tcd_decode_tile( p_j2k->m_tcd,
|
||||
&l_tcp->m_data,
|
||||
p_tile_index,
|
||||
p_j2k->cstr_index, p_manager) ) {
|
||||
opj_j2k_tcp_destroy(l_tcp);
|
||||
p_j2k->m_specific_param.m_decoder.m_state |= 0x8000;/*FIXME J2K_DEC_STATE_ERR;*/
|
||||
opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n");
|
||||
|
|
|
@ -280,10 +280,9 @@ typedef struct opj_tcp
|
|||
opj_tccp_t *tccps;
|
||||
/** number of tile parts for the tile. */
|
||||
OPJ_UINT32 m_nb_tile_parts;
|
||||
/** data for the tile */
|
||||
OPJ_BYTE * m_data;
|
||||
/** size of data */
|
||||
OPJ_UINT32 m_data_size;
|
||||
|
||||
opj_seg_buf_t m_data;
|
||||
|
||||
/** encoding norms */
|
||||
OPJ_FLOAT64 * mct_norms;
|
||||
/** the mct decoding matrix */
|
||||
|
|
|
@ -33,7 +33,19 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif /* _WIN32 */
|
||||
#else /* _WIN32 */
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
# include <unistd.h>
|
||||
# include <sys/mman.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "opj_includes.h"
|
||||
|
||||
|
@ -129,6 +141,103 @@ static OPJ_BOOL opj_seek_from_file (OPJ_OFF_T p_nb_bytes, FILE * p_user_data)
|
|||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef void* opj_handle_t;
|
||||
#else
|
||||
typedef OPJ_INT32 opj_handle_t;
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct opj_buf_info
|
||||
{
|
||||
OPJ_BYTE *buf;
|
||||
OPJ_OFF_T off;
|
||||
OPJ_SIZE_T len;
|
||||
opj_handle_t fd; // for file mapping
|
||||
} opj_buf_info_t;
|
||||
|
||||
static void opj_free_buffer_info(void* user_data) {
|
||||
if (user_data)
|
||||
opj_free(user_data);
|
||||
}
|
||||
|
||||
static OPJ_SIZE_T opj_zero_copy_read_from_buffer(void ** p_buffer,
|
||||
OPJ_SIZE_T p_nb_bytes,
|
||||
opj_buf_info_t* p_source_buffer)
|
||||
{
|
||||
OPJ_SIZE_T l_nb_read = 0;
|
||||
|
||||
if (p_source_buffer->off + p_nb_bytes < p_source_buffer->len) {
|
||||
l_nb_read = p_nb_bytes;
|
||||
}
|
||||
|
||||
*p_buffer = p_source_buffer->buf + p_source_buffer->off;
|
||||
p_source_buffer->off += l_nb_read;
|
||||
|
||||
return l_nb_read ? l_nb_read : ((OPJ_SIZE_T)-1);
|
||||
}
|
||||
|
||||
static OPJ_SIZE_T opj_read_from_buffer(void * p_buffer,
|
||||
OPJ_SIZE_T p_nb_bytes,
|
||||
opj_buf_info_t* p_source_buffer)
|
||||
{
|
||||
OPJ_SIZE_T l_nb_read;
|
||||
|
||||
if (p_source_buffer->off + p_nb_bytes < p_source_buffer->len)
|
||||
{
|
||||
l_nb_read = p_nb_bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
l_nb_read = (OPJ_SIZE_T)(p_source_buffer->len - p_source_buffer->off);
|
||||
}
|
||||
memcpy(p_buffer, p_source_buffer->buf + p_source_buffer->off, l_nb_read);
|
||||
p_source_buffer->off += l_nb_read;
|
||||
|
||||
return l_nb_read ? l_nb_read : ((OPJ_SIZE_T)-1);
|
||||
}
|
||||
|
||||
static OPJ_SIZE_T opj_write_from_buffer(void * p_buffer,
|
||||
OPJ_SIZE_T p_nb_bytes,
|
||||
opj_buf_info_t* p_source_buffer)
|
||||
{
|
||||
memcpy(p_source_buffer->buf + p_source_buffer->off, p_buffer, p_nb_bytes);
|
||||
p_source_buffer->off += p_nb_bytes;
|
||||
p_source_buffer->len += p_nb_bytes;
|
||||
|
||||
return p_nb_bytes;
|
||||
}
|
||||
|
||||
static OPJ_OFF_T opj_skip_from_buffer(OPJ_OFF_T p_nb_bytes,
|
||||
opj_buf_info_t * p_source_buffer)
|
||||
{
|
||||
if (p_source_buffer->off + p_nb_bytes < (OPJ_OFF_T)p_source_buffer->len) {
|
||||
p_source_buffer->off += p_nb_bytes;
|
||||
}
|
||||
else {
|
||||
p_source_buffer->off = p_source_buffer->len;
|
||||
}
|
||||
return p_nb_bytes;
|
||||
}
|
||||
|
||||
static OPJ_BOOL opj_seek_from_buffer(OPJ_OFF_T p_nb_bytes,
|
||||
opj_buf_info_t * p_source_buffer)
|
||||
{
|
||||
if (p_nb_bytes < (OPJ_OFF_T)p_source_buffer->len)
|
||||
{
|
||||
p_source_buffer->off = p_nb_bytes;
|
||||
}
|
||||
else {
|
||||
p_source_buffer->off = p_source_buffer->len;
|
||||
}
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef OPJ_STATIC
|
||||
BOOL APIENTRY
|
||||
|
@ -917,6 +1026,8 @@ void OPJ_CALLCONV opj_destroy_cstr_index(opj_codestream_index_t **p_cstr_index)
|
|||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (const char *fname, OPJ_BOOL p_is_read_stream)
|
||||
{
|
||||
return opj_stream_create_file_stream(fname, OPJ_J2K_STREAM_CHUNK_SIZE, p_is_read_stream);
|
||||
|
@ -958,3 +1069,273 @@ opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (
|
|||
|
||||
return l_stream;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
static void opj_set_up_buffer_stream(opj_stream_t* l_stream, OPJ_SIZE_T len, OPJ_BOOL p_is_read_stream) {
|
||||
opj_stream_set_user_data_length(l_stream, len);
|
||||
|
||||
if (p_is_read_stream) {
|
||||
opj_stream_set_read_function(l_stream, (opj_stream_read_fn)opj_read_from_buffer);
|
||||
opj_stream_set_zero_copy_read_function(l_stream, (opj_stream_zero_copy_read_fn)opj_zero_copy_read_from_buffer);
|
||||
}
|
||||
else
|
||||
opj_stream_set_write_function(l_stream, (opj_stream_write_fn)opj_write_from_buffer);
|
||||
opj_stream_set_skip_function(l_stream, (opj_stream_skip_fn)opj_skip_from_buffer);
|
||||
opj_stream_set_seek_function(l_stream, (opj_stream_seek_fn)opj_seek_from_buffer);
|
||||
}
|
||||
|
||||
opj_stream_t* OPJ_CALLCONV opj_stream_create_buffer_stream(OPJ_BYTE *buf,
|
||||
OPJ_SIZE_T len,
|
||||
OPJ_BOOL p_is_read_stream)
|
||||
{
|
||||
opj_stream_t* l_stream;
|
||||
opj_buf_info_t* p_source_buffer = NULL;
|
||||
|
||||
if (!buf || !len)
|
||||
return NULL;
|
||||
|
||||
p_source_buffer = (opj_buf_info_t*)opj_malloc(sizeof(opj_buf_info_t));
|
||||
if (!p_source_buffer)
|
||||
return NULL;
|
||||
|
||||
l_stream = opj_stream_create(0,p_is_read_stream);
|
||||
if (!l_stream) {
|
||||
opj_free(p_source_buffer);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
memset(p_source_buffer, 0, sizeof(opj_buf_info_t));
|
||||
p_source_buffer->buf = buf;
|
||||
p_source_buffer->off = 0;
|
||||
p_source_buffer->len = len;
|
||||
|
||||
opj_stream_set_user_data(l_stream, p_source_buffer, opj_free_buffer_info);
|
||||
opj_set_up_buffer_stream(l_stream, p_source_buffer->len, p_is_read_stream);
|
||||
return l_stream;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
OPJ_INT32 opj_get_file_open_mode(const char* mode)
|
||||
{
|
||||
OPJ_INT32 m = -1;
|
||||
switch (mode[0]) {
|
||||
case 'r':
|
||||
m = O_RDONLY;
|
||||
if (mode[1] == '+')
|
||||
m = O_RDWR;
|
||||
break;
|
||||
case 'w':
|
||||
case 'a':
|
||||
m = O_RDWR | O_CREAT;
|
||||
if (mode[0] == 'w')
|
||||
m |= O_TRUNC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static OPJ_UINT64 opj_size_proc(opj_handle_t fd)
|
||||
{
|
||||
ULARGE_INTEGER m;
|
||||
m.LowPart = GetFileSize(fd, &m.HighPart);
|
||||
return(m.QuadPart);
|
||||
}
|
||||
|
||||
|
||||
static void* opj_map(opj_handle_t fd, OPJ_SIZE_T len) {
|
||||
void* ptr = NULL;
|
||||
HANDLE hMapFile = NULL;
|
||||
|
||||
if (!fd || !len)
|
||||
return NULL;
|
||||
|
||||
/* Passing in 0 for the maximum file size indicates that we
|
||||
would like to create a file mapping object for the full file size */
|
||||
hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if (hMapFile == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
ptr = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
|
||||
CloseHandle(hMapFile);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static OPJ_INT32 opj_unmap(void* ptr, OPJ_SIZE_T len){
|
||||
OPJ_INT32 rc = -1;
|
||||
if (ptr)
|
||||
rc = UnmapViewOfFile(ptr) ? 0 : -1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static opj_handle_t opj_open_fd(const char* fname, const char* mode) {
|
||||
void* fd = NULL;
|
||||
OPJ_INT32 m = -1;
|
||||
DWORD dwMode = 0;
|
||||
|
||||
if (!fname)
|
||||
return (opj_handle_t)-1;
|
||||
|
||||
|
||||
m = opj_get_file_open_mode(mode);
|
||||
switch (m) {
|
||||
case O_RDONLY:
|
||||
dwMode = OPEN_EXISTING;
|
||||
break;
|
||||
case O_RDWR:
|
||||
dwMode = OPEN_ALWAYS;
|
||||
break;
|
||||
case O_RDWR | O_CREAT:
|
||||
dwMode = OPEN_ALWAYS;
|
||||
break;
|
||||
case O_RDWR | O_TRUNC:
|
||||
dwMode = CREATE_ALWAYS;
|
||||
break;
|
||||
case O_RDWR | O_CREAT | O_TRUNC:
|
||||
dwMode = CREATE_ALWAYS;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fd = (opj_handle_t)CreateFileA(fname,
|
||||
(m == O_RDONLY) ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
|
||||
(m == O_RDONLY) ? FILE_ATTRIBUTE_READONLY : FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
if (fd == INVALID_HANDLE_VALUE) {
|
||||
return (opj_handle_t)-1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static OPJ_INT32 opj_close_fd(opj_handle_t fd) {
|
||||
OPJ_INT32 rc = -1;
|
||||
if (fd) {
|
||||
rc = CloseHandle(fd) ? 0 : -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static OPJ_UINT64 opj_size_proc(opj_handle_t fd)
|
||||
{
|
||||
struct stat sb;
|
||||
if (!fd)
|
||||
return 0;
|
||||
|
||||
if (fstat(fd, &sb)<0)
|
||||
return(0);
|
||||
else
|
||||
return((OPJ_UINT64)sb.st_size);
|
||||
}
|
||||
|
||||
static void* opj_map(opj_handle_t fd, OPJ_SIZE_T len) {
|
||||
void* ptr = NULL;
|
||||
OPJ_UINT64 size64 = 0;
|
||||
|
||||
if (!fd)
|
||||
return NULL;
|
||||
|
||||
size64 = opj_size_proc(fd);
|
||||
ptr = (void*)mmap(0, (size_t)size64, PROT_READ, MAP_SHARED, fd, 0);
|
||||
return ptr == (void*)-1 ? NULL : ptr;
|
||||
}
|
||||
|
||||
static OPJ_INT32 opj_unmap(void* ptr, OPJ_SIZE_T len) {
|
||||
if (ptr)
|
||||
munmap(ptr, (off_t)len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static opj_handle_t opj_open_fd(const char* fname, const char* mode) {
|
||||
opj_handle_t fd = 0;
|
||||
OPJ_INT32 m = -1;
|
||||
if (!fname) {
|
||||
return (opj_handle_t )-1;
|
||||
}
|
||||
m = opj_get_file_open_mode(mode);
|
||||
fd = open(fname, m, 0666);
|
||||
if (fd < 0) {
|
||||
#ifdef DEBUG_ERRNO
|
||||
if (errno > 0 && strerror(errno) != NULL) {
|
||||
printf("%s: %s", fname, strerror(errno));
|
||||
}
|
||||
else {
|
||||
printf("%s: Cannot open", fname);
|
||||
}
|
||||
#endif
|
||||
return (opj_handle_t )-1;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
static OPJ_INT32 opj_close_fd(opj_handle_t fd) {
|
||||
if (!fd)
|
||||
return 0;
|
||||
return (close(fd));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static void opj_mem_map_free(void* user_data) {
|
||||
if (user_data) {
|
||||
opj_buf_info_t* buffer_info = (opj_buf_info_t*)user_data;
|
||||
opj_unmap(buffer_info->buf, buffer_info->len);
|
||||
opj_close_fd(buffer_info->fd);
|
||||
opj_free(buffer_info);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Currently, only read streams are supported for memory mapped files.
|
||||
*/
|
||||
opj_stream_t* OPJ_CALLCONV opj_stream_create_mapped_file_read_stream(const char *fname)
|
||||
{
|
||||
opj_stream_t* l_stream = NULL;
|
||||
opj_buf_info_t* buffer_info = NULL;
|
||||
void* mapped_view = NULL;
|
||||
OPJ_BOOL p_is_read_stream = OPJ_TRUE;
|
||||
|
||||
opj_handle_t fd = opj_open_fd(fname, p_is_read_stream ? "r" : "w");
|
||||
if (fd == (opj_handle_t)-1)
|
||||
return NULL;
|
||||
|
||||
buffer_info = (opj_buf_info_t*)opj_malloc(sizeof(opj_buf_info_t));
|
||||
memset(buffer_info, 0, sizeof(opj_buf_info_t));
|
||||
buffer_info->fd = fd;
|
||||
buffer_info->len = (OPJ_SIZE_T)opj_size_proc(fd);
|
||||
|
||||
l_stream = opj_stream_create(0, p_is_read_stream);
|
||||
if (!l_stream) {
|
||||
opj_mem_map_free(buffer_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mapped_view = opj_map(fd, buffer_info->len);
|
||||
if (!mapped_view) {
|
||||
opj_stream_destroy(l_stream);
|
||||
opj_mem_map_free(buffer_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer_info->buf = mapped_view;
|
||||
buffer_info->off = 0;
|
||||
|
||||
opj_stream_set_user_data(l_stream, buffer_info, (opj_stream_free_user_data_fn)opj_mem_map_free);
|
||||
opj_set_up_buffer_stream(l_stream, buffer_info->len, p_is_read_stream);
|
||||
|
||||
|
||||
return l_stream;
|
||||
}
|
||||
|
||||
|
|
|
@ -568,6 +568,7 @@ typedef struct opj_dparameters {
|
|||
} opj_dparameters_t;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* JPEG2000 codec V2.
|
||||
* */
|
||||
|
@ -592,6 +593,12 @@ typedef void * opj_codec_t;
|
|||
*/
|
||||
typedef OPJ_SIZE_T (* opj_stream_read_fn) (void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data) ;
|
||||
|
||||
/*
|
||||
* Callback function prototype for zero copy read function
|
||||
*/
|
||||
typedef OPJ_SIZE_T(*opj_stream_zero_copy_read_fn) (void ** p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data);
|
||||
|
||||
|
||||
/*
|
||||
* Callback function prototype for write function
|
||||
*/
|
||||
|
@ -1128,6 +1135,15 @@ OPJ_API void OPJ_CALLCONV opj_stream_destroy(opj_stream_t* p_stream);
|
|||
*/
|
||||
OPJ_API void OPJ_CALLCONV opj_stream_set_read_function(opj_stream_t* p_stream, opj_stream_read_fn p_function);
|
||||
|
||||
/**
|
||||
* Sets the given function to be used as a zero copy read function.
|
||||
* NOTE: this feature is only available for memory mapped and buffer backed streams, not file streams
|
||||
* @param p_stream the stream to modify
|
||||
* @param p_function the function to use a read function.
|
||||
*/
|
||||
OPJ_API void OPJ_CALLCONV opj_stream_set_zero_copy_read_function(opj_stream_t* p_stream, opj_stream_zero_copy_read_fn p_function);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the given function to be used as a write function.
|
||||
* @param p_stream the stream to modify
|
||||
|
@ -1180,6 +1196,11 @@ OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_default_file_stream (const
|
|||
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream (const char *fname,
|
||||
OPJ_SIZE_T p_buffer_size,
|
||||
OPJ_BOOL p_is_read_stream);
|
||||
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_buffer_stream(OPJ_BYTE *buf,
|
||||
OPJ_SIZE_T len,
|
||||
OPJ_BOOL p_is_read_stream);
|
||||
|
||||
OPJ_API opj_stream_t* OPJ_CALLCONV opj_stream_create_mapped_file_read_stream(const char *fname);
|
||||
|
||||
/*
|
||||
==========================================================
|
||||
|
|
|
@ -177,6 +177,8 @@ static INLINE long opj_lrintf(float f) {
|
|||
#include "opj_malloc.h"
|
||||
#include "event.h"
|
||||
#include "function_list.h"
|
||||
#include "vector.h"
|
||||
#include "segmented_stream.h"
|
||||
#include "bio.h"
|
||||
#include "cio.h"
|
||||
|
||||
|
@ -198,6 +200,7 @@ static INLINE long opj_lrintf(float f) {
|
|||
#include "mct.h"
|
||||
#include "opj_intmath.h"
|
||||
|
||||
|
||||
#ifdef USE_JPIP
|
||||
#include "cidx_manager.h"
|
||||
#include "indexbox_manager.h"
|
||||
|
|
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
* 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) 2015, Aaron Boxer
|
||||
* 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"
|
||||
|
||||
/* #define DEBUG_SEG_BUF */
|
||||
|
||||
|
||||
OPJ_BOOL opj_min_buf_vec_copy_to_contiguous_buffer(opj_vec_t* min_buf_vec, OPJ_BYTE* buffer) {
|
||||
OPJ_INT32 i = 0;
|
||||
OPJ_SIZE_T offset = 0;
|
||||
|
||||
if (!buffer || !min_buf_vec)
|
||||
return OPJ_FALSE;
|
||||
|
||||
for (i = 0; i < min_buf_vec->size; ++i) {
|
||||
opj_min_buf_t* seg = (opj_min_buf_t*)opj_vec_get(min_buf_vec, i);
|
||||
if (seg->len)
|
||||
memcpy(buffer + offset, seg->buf, seg->len);
|
||||
offset += seg->len;
|
||||
}
|
||||
return OPJ_TRUE;
|
||||
|
||||
}
|
||||
|
||||
OPJ_BOOL opj_min_buf_vec_push_back(opj_vec_t* buf_vec, OPJ_BYTE* buf, OPJ_UINT16 len) {
|
||||
opj_min_buf_t* seg = NULL;
|
||||
if (!buf_vec || !buf || !len)
|
||||
return OPJ_FALSE;
|
||||
|
||||
if (!buf_vec->data) {
|
||||
opj_vec_init(buf_vec);
|
||||
buf_vec->owns_data = OPJ_TRUE;
|
||||
}
|
||||
|
||||
seg = (opj_min_buf_t*)opj_malloc(sizeof(opj_buf_t));
|
||||
if (!seg)
|
||||
return OPJ_FALSE;
|
||||
|
||||
seg->buf = buf;
|
||||
seg->len = len;
|
||||
if (!opj_vec_push_back(buf_vec, seg)) {
|
||||
opj_free(seg);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
OPJ_UINT16 opj_min_buf_vec_get_len(opj_vec_t* min_buf_vec) {
|
||||
OPJ_INT32 i = 0;
|
||||
OPJ_UINT16 len = 0;
|
||||
if (!min_buf_vec || !min_buf_vec->data)
|
||||
return 0;
|
||||
for (i = 0; i < min_buf_vec->size; ++i) {
|
||||
opj_min_buf_t* seg = (opj_min_buf_t*)opj_vec_get(min_buf_vec, i);
|
||||
if (seg)
|
||||
len += seg->len;
|
||||
}
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/* Segmented Buffer Stream */
|
||||
|
||||
static void opj_seg_buf_increment(opj_seg_buf_t * seg_buf)
|
||||
{
|
||||
opj_buf_t* cur_seg = NULL;
|
||||
if (seg_buf == NULL || seg_buf->cur_seg_id == seg_buf->segments.size-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
cur_seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, seg_buf->cur_seg_id);
|
||||
if (cur_seg->offset == cur_seg->len &&
|
||||
seg_buf->cur_seg_id < seg_buf->segments.size -1) {
|
||||
seg_buf->cur_seg_id++;
|
||||
}
|
||||
}
|
||||
|
||||
static OPJ_SIZE_T opj_seg_buf_read(opj_seg_buf_t * seg_buf,
|
||||
void * p_buffer,
|
||||
OPJ_SIZE_T p_nb_bytes)
|
||||
{
|
||||
OPJ_SIZE_T bytes_in_current_segment;
|
||||
OPJ_SIZE_T bytes_to_read;
|
||||
OPJ_SIZE_T total_bytes_read;
|
||||
OPJ_SIZE_T bytes_left_to_read;
|
||||
OPJ_SIZE_T bytes_remaining_in_file;
|
||||
|
||||
if (p_buffer == NULL || p_nb_bytes == 0 || seg_buf == NULL)
|
||||
return 0;
|
||||
|
||||
/*don't try to read more bytes than are available */
|
||||
bytes_remaining_in_file = seg_buf->data_len - opj_seg_buf_get_global_offset(seg_buf);
|
||||
if (p_nb_bytes > bytes_remaining_in_file) {
|
||||
#ifdef DEBUG_SEG_BUF
|
||||
printf("Warning: attempt to read past end of segmented buffer\n");
|
||||
#endif
|
||||
p_nb_bytes = bytes_remaining_in_file;
|
||||
}
|
||||
|
||||
total_bytes_read = 0;
|
||||
bytes_left_to_read = p_nb_bytes;
|
||||
while (bytes_left_to_read > 0 && seg_buf->cur_seg_id < seg_buf->segments.size) {
|
||||
opj_buf_t* cur_seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, seg_buf->cur_seg_id);
|
||||
bytes_in_current_segment = (OPJ_SIZE_T)(cur_seg->len - cur_seg->offset);
|
||||
|
||||
bytes_to_read = (bytes_left_to_read < bytes_in_current_segment) ?
|
||||
bytes_left_to_read : bytes_in_current_segment;
|
||||
|
||||
if (p_buffer) {
|
||||
memcpy((OPJ_BYTE*)p_buffer + total_bytes_read,cur_seg->buf + cur_seg->offset, bytes_to_read);
|
||||
}
|
||||
opj_seg_buf_incr_cur_seg_offset(seg_buf,bytes_to_read);
|
||||
|
||||
total_bytes_read += bytes_to_read;
|
||||
bytes_left_to_read -= bytes_to_read;
|
||||
|
||||
|
||||
}
|
||||
return total_bytes_read ? total_bytes_read : (OPJ_SIZE_T)-1;
|
||||
}
|
||||
|
||||
|
||||
static OPJ_OFF_T opj_seg_buf_skip(OPJ_OFF_T p_nb_bytes, opj_seg_buf_t * seg_buf)
|
||||
{
|
||||
OPJ_SIZE_T bytes_in_current_segment;
|
||||
OPJ_SIZE_T bytes_remaining;
|
||||
|
||||
if (!seg_buf)
|
||||
return p_nb_bytes;
|
||||
|
||||
if (p_nb_bytes + opj_seg_buf_get_global_offset(seg_buf)> (OPJ_OFF_T)seg_buf->data_len) {
|
||||
#ifdef DEBUG_SEG_BUF
|
||||
printf("Warning: attempt to skip past end of segmented buffer\n");
|
||||
#endif
|
||||
return p_nb_bytes;
|
||||
}
|
||||
|
||||
if (p_nb_bytes == 0)
|
||||
return 0;
|
||||
|
||||
bytes_remaining = (OPJ_SIZE_T)p_nb_bytes;
|
||||
while (seg_buf->cur_seg_id < seg_buf->segments.size && bytes_remaining > 0) {
|
||||
|
||||
opj_buf_t* cur_seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, seg_buf->cur_seg_id);
|
||||
bytes_in_current_segment = (OPJ_SIZE_T)(cur_seg->len -cur_seg->offset);
|
||||
|
||||
/* hoover up all the bytes in this segment, and move to the next one */
|
||||
if (bytes_in_current_segment > bytes_remaining) {
|
||||
|
||||
opj_seg_buf_incr_cur_seg_offset(seg_buf, bytes_in_current_segment);
|
||||
|
||||
bytes_remaining -= bytes_in_current_segment;
|
||||
cur_seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, seg_buf->cur_seg_id);
|
||||
}
|
||||
else /* bingo! we found the segment */
|
||||
{
|
||||
opj_seg_buf_incr_cur_seg_offset(seg_buf, bytes_remaining);
|
||||
return p_nb_bytes;
|
||||
}
|
||||
}
|
||||
return p_nb_bytes;
|
||||
}
|
||||
|
||||
static OPJ_BOOL opj_seg_buf_seek(OPJ_OFF_T p_nb_bytes, opj_seg_buf_t* seg_buf)
|
||||
{
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
static OPJ_BOOL opj_seg_buf_add_segment(opj_seg_buf_t* seg_buf, OPJ_BYTE* buf, OPJ_SIZE_T len) {
|
||||
opj_buf_t* new_seg = NULL;
|
||||
if (!seg_buf)
|
||||
return OPJ_FALSE;
|
||||
new_seg = (opj_buf_t*)opj_malloc(sizeof(opj_buf_t));
|
||||
if (!new_seg)
|
||||
return OPJ_FALSE;
|
||||
|
||||
memset(new_seg, 0, sizeof(opj_buf_t));
|
||||
new_seg->buf = buf;
|
||||
new_seg->len = len;
|
||||
if (!opj_vec_push_back(&seg_buf->segments, new_seg)) {
|
||||
opj_free(new_seg);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
seg_buf->cur_seg_id = seg_buf->segments.size - 1;
|
||||
seg_buf->data_len += len;
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void opj_seg_buf_cleanup(opj_seg_buf_t* seg_buf) {
|
||||
OPJ_INT32 i;
|
||||
if (!seg_buf)
|
||||
return;
|
||||
for (i = 0; i < seg_buf->segments.size; ++i) {
|
||||
opj_buf_t* seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, i);
|
||||
if (seg) {
|
||||
opj_buf_free(seg);
|
||||
}
|
||||
}
|
||||
opj_vec_cleanup(&seg_buf->segments);
|
||||
}
|
||||
|
||||
void opj_seg_buf_rewind(opj_seg_buf_t* seg_buf) {
|
||||
OPJ_INT32 i;
|
||||
if (!seg_buf)
|
||||
return;
|
||||
for (i = 0; i < seg_buf->segments.size; ++i) {
|
||||
opj_buf_t* seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, i);
|
||||
if (seg) {
|
||||
seg->offset = 0;
|
||||
}
|
||||
}
|
||||
seg_buf->cur_seg_id = 0;
|
||||
}
|
||||
|
||||
|
||||
OPJ_BOOL opj_seg_buf_push_back(opj_seg_buf_t* seg_buf, OPJ_BYTE* buf, OPJ_SIZE_T len) {
|
||||
opj_buf_t* seg = NULL;
|
||||
if (!seg_buf || !buf || !len)
|
||||
return OPJ_FALSE;
|
||||
|
||||
if (!seg_buf->segments.data) {
|
||||
opj_vec_init(&seg_buf->segments);
|
||||
/* let segmented buffer free the segment and its internal buffer,
|
||||
so don't make vector manage memory */
|
||||
seg_buf->segments.owns_data = OPJ_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!opj_seg_buf_add_segment(seg_buf, buf, len))
|
||||
return OPJ_FALSE;
|
||||
|
||||
seg = (opj_buf_t*)opj_vec_back(&seg_buf->segments);
|
||||
seg->owns_data = OPJ_FALSE;
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
OPJ_BOOL opj_seg_buf_alloc_and_push_back(opj_seg_buf_t* seg_buf, OPJ_SIZE_T len) {
|
||||
opj_buf_t* seg = NULL;
|
||||
OPJ_BYTE* buf = NULL;
|
||||
if (!seg_buf || !len)
|
||||
return OPJ_FALSE;
|
||||
|
||||
if (!seg_buf->segments.data) {
|
||||
opj_vec_init(&seg_buf->segments);
|
||||
/* we want to free the segment and its internal buffer, so don't make vector manage memory*/
|
||||
seg_buf->segments.owns_data = OPJ_FALSE;
|
||||
}
|
||||
|
||||
|
||||
buf = (OPJ_BYTE*)opj_malloc(len);
|
||||
if (!buf)
|
||||
return OPJ_FALSE;
|
||||
|
||||
if (!opj_seg_buf_add_segment(seg_buf, buf, len)) {
|
||||
opj_free(buf);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
seg = (opj_buf_t*)opj_vec_back(&seg_buf->segments);
|
||||
seg->owns_data = OPJ_TRUE;
|
||||
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
void opj_seg_buf_incr_cur_seg_offset(opj_seg_buf_t* seg_buf, OPJ_OFF_T offset) {
|
||||
opj_buf_t* cur_seg = NULL;
|
||||
if (!seg_buf)
|
||||
return;
|
||||
cur_seg = (opj_buf_t*)(seg_buf->segments.data[seg_buf->cur_seg_id]);
|
||||
opj_buf_incr_offset(cur_seg, offset);
|
||||
if (cur_seg->offset == cur_seg->len) {
|
||||
opj_seg_buf_increment(seg_buf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Zero copy read of contiguous chunk from current segment.
|
||||
* Returns OPJ_FALSE if unable to get a contiguous chunk, OPJ_TRUE otherwise
|
||||
*/
|
||||
OPJ_BOOL opj_seg_buf_zero_copy_read(opj_seg_buf_t* seg_buf,
|
||||
OPJ_BYTE** ptr,
|
||||
OPJ_SIZE_T chunk_len) {
|
||||
opj_buf_t* cur_seg = NULL;
|
||||
if (!seg_buf)
|
||||
return OPJ_FALSE;
|
||||
cur_seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, seg_buf->cur_seg_id);
|
||||
if (!cur_seg)
|
||||
return OPJ_FALSE;
|
||||
|
||||
if (cur_seg->offset + chunk_len <= cur_seg->len) {
|
||||
*ptr = cur_seg->buf + cur_seg->offset;
|
||||
opj_seg_buf_read(seg_buf, NULL, chunk_len);
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
OPJ_BOOL opj_seg_buf_copy_to_contiguous_buffer(opj_seg_buf_t* seg_buf, OPJ_BYTE* buffer) {
|
||||
OPJ_INT32 i = 0;
|
||||
OPJ_SIZE_T offset = 0;
|
||||
|
||||
if (!buffer || !seg_buf)
|
||||
return OPJ_FALSE;
|
||||
|
||||
for (i = 0; i < seg_buf->segments.size; ++i) {
|
||||
opj_buf_t* seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, i);
|
||||
if (seg->len)
|
||||
memcpy(buffer + offset, seg->buf, seg->len);
|
||||
offset += seg->len;
|
||||
}
|
||||
return OPJ_TRUE;
|
||||
|
||||
}
|
||||
|
||||
OPJ_BYTE* opj_seg_buf_get_global_ptr(opj_seg_buf_t* seg_buf) {
|
||||
opj_buf_t* cur_seg = NULL;
|
||||
if (!seg_buf)
|
||||
return NULL;
|
||||
cur_seg = (opj_buf_t*)(seg_buf->segments.data[seg_buf->cur_seg_id]);
|
||||
return (cur_seg) ? (cur_seg->buf + cur_seg->offset) : NULL;
|
||||
}
|
||||
|
||||
OPJ_SIZE_T opj_seg_buf_get_cur_seg_len(opj_seg_buf_t* seg_buf) {
|
||||
opj_buf_t* cur_seg = NULL;
|
||||
if (!seg_buf)
|
||||
return 0;
|
||||
cur_seg = (opj_buf_t*)(opj_vec_get(&seg_buf->segments, seg_buf->cur_seg_id));
|
||||
return (cur_seg) ? (OPJ_SIZE_T)(cur_seg->len - cur_seg->offset) : 0;
|
||||
}
|
||||
|
||||
OPJ_OFF_T opj_seg_buf_get_cur_seg_offset(opj_seg_buf_t* seg_buf) {
|
||||
opj_buf_t* cur_seg = NULL;
|
||||
if (!seg_buf)
|
||||
return 0;
|
||||
cur_seg = (opj_buf_t*)(opj_vec_get(&seg_buf->segments, seg_buf->cur_seg_id));
|
||||
return (cur_seg) ? (OPJ_OFF_T)(cur_seg->offset) : 0;
|
||||
}
|
||||
|
||||
|
||||
OPJ_OFF_T opj_seg_buf_get_global_offset(opj_seg_buf_t* seg_buf) {
|
||||
OPJ_INT32 i = 0;
|
||||
OPJ_OFF_T offset = 0;
|
||||
|
||||
if (!seg_buf)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < seg_buf->cur_seg_id; ++i) {
|
||||
opj_buf_t* seg = (opj_buf_t*)opj_vec_get(&seg_buf->segments, i);
|
||||
offset += seg->len;
|
||||
}
|
||||
return offset + opj_seg_buf_get_cur_seg_offset(seg_buf);
|
||||
}
|
||||
|
||||
|
||||
void opj_buf_incr_offset(opj_buf_t* buf, OPJ_OFF_T off) {
|
||||
if (!buf)
|
||||
return;
|
||||
/* we allow the offset to move to one location beyond end of buffer segment*/
|
||||
if (buf->offset + off > (OPJ_OFF_T)buf->len) {
|
||||
#ifdef DEBUG_SEG_BUF
|
||||
printf("Warning: attempt to increment buffer offset out of bounds\n");
|
||||
#endif
|
||||
buf->offset = buf->len;
|
||||
}
|
||||
buf->offset += off;
|
||||
}
|
||||
|
||||
void opj_buf_free(opj_buf_t* buffer) {
|
||||
if (!buffer)
|
||||
return;
|
||||
if (buffer->buf && buffer->owns_data)
|
||||
opj_free(buffer->buf);
|
||||
opj_free(buffer);
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* 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) 2015, Aaron Boxer
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __SEGMENTED_STREAM_H
|
||||
#define __SEGMENTED_STREAM_H
|
||||
|
||||
/*
|
||||
Smart wrapper to low level C array
|
||||
*/
|
||||
|
||||
typedef struct opj_min_buf {
|
||||
OPJ_BYTE *buf; /* internal array*/
|
||||
OPJ_UINT16 len; /* length of array */
|
||||
} opj_min_buf_t;
|
||||
|
||||
/*
|
||||
Copy all segments, in sequence, into contiguous array
|
||||
*/
|
||||
OPJ_BOOL opj_min_buf_vec_copy_to_contiguous_buffer(opj_vec_t* min_buf_vec, OPJ_BYTE* buffer);
|
||||
|
||||
/*
|
||||
Push buffer to back of min buf vector
|
||||
*/
|
||||
OPJ_BOOL opj_min_buf_vec_push_back(opj_vec_t* buf_vec, OPJ_BYTE* buf, OPJ_UINT16 len);
|
||||
|
||||
/*
|
||||
Sum lengths of all buffers
|
||||
*/
|
||||
|
||||
OPJ_UINT16 opj_min_buf_vec_get_len(opj_vec_t* min_buf_vec);
|
||||
|
||||
typedef struct opj_buf {
|
||||
OPJ_BYTE *buf; /* internal array*/
|
||||
OPJ_OFF_T offset; /* current offset into array */
|
||||
OPJ_SIZE_T len; /* length of array */
|
||||
OPJ_BOOL owns_data; /* OPJ_TRUE if buffer manages the buf array */
|
||||
} opj_buf_t;
|
||||
|
||||
|
||||
/*
|
||||
Increment buffer offset
|
||||
*/
|
||||
void opj_buf_incr_offset(opj_buf_t* buf, OPJ_OFF_T off);
|
||||
|
||||
/*
|
||||
Free buffer and also its internal array if owns_data is true
|
||||
*/
|
||||
void opj_buf_free(opj_buf_t* buf);
|
||||
|
||||
|
||||
/* Segmented Buffer Interface
|
||||
|
||||
A segmented buffer stores a list of buffers, or segments, but can be treated as one single
|
||||
contiguous buffer.
|
||||
|
||||
*/
|
||||
typedef struct opj_seg_buf
|
||||
{
|
||||
OPJ_SIZE_T data_len; /* total length of all segments*/
|
||||
OPJ_INT32 cur_seg_id; /* current index into segments vector */
|
||||
opj_vec_t segments; /* vector of segments */
|
||||
|
||||
} opj_seg_buf_t;
|
||||
|
||||
/*
|
||||
Wrap existing array and add to the back of the segmented buffer.
|
||||
*/
|
||||
OPJ_BOOL opj_seg_buf_push_back(opj_seg_buf_t* seg_buf, OPJ_BYTE* buf, OPJ_SIZE_T len);
|
||||
|
||||
/*
|
||||
Allocate array and add to the back of the segmented buffer
|
||||
*/
|
||||
OPJ_BOOL opj_seg_buf_alloc_and_push_back(opj_seg_buf_t* seg_buf, OPJ_SIZE_T len);
|
||||
|
||||
/*
|
||||
Increment offset of current segment
|
||||
*/
|
||||
void opj_seg_buf_incr_cur_seg_offset(opj_seg_buf_t* seg_buf, OPJ_OFF_T offset);
|
||||
|
||||
/*
|
||||
Get length of current segment
|
||||
*/
|
||||
OPJ_SIZE_T opj_seg_buf_get_cur_seg_len(opj_seg_buf_t* seg_buf);
|
||||
|
||||
/*
|
||||
Get offset of current segment
|
||||
*/
|
||||
OPJ_OFF_T opj_seg_buf_get_cur_seg_offset(opj_seg_buf_t* seg_buf);
|
||||
|
||||
/*
|
||||
Treat segmented buffer as single contiguous buffer, and get current pointer
|
||||
*/
|
||||
OPJ_BYTE* opj_seg_buf_get_global_ptr(opj_seg_buf_t* seg_buf);
|
||||
|
||||
/*
|
||||
Treat segmented buffer as single contiguous buffer, and get current offset
|
||||
*/
|
||||
OPJ_OFF_T opj_seg_buf_get_global_offset(opj_seg_buf_t* seg_buf);
|
||||
|
||||
/*
|
||||
Reset all offsets to zero, and set current segment to beginning of list
|
||||
*/
|
||||
void opj_seg_buf_rewind(opj_seg_buf_t* seg_buf);
|
||||
|
||||
/*
|
||||
Copy all segments, in sequence, into contiguous array
|
||||
*/
|
||||
OPJ_BOOL opj_seg_buf_copy_to_contiguous_buffer(opj_seg_buf_t* seg_buf, OPJ_BYTE* buffer);
|
||||
|
||||
/*
|
||||
Cleans up internal resources
|
||||
*/
|
||||
void opj_seg_buf_cleanup(opj_seg_buf_t* seg_buf);
|
||||
|
||||
/*
|
||||
Return current pointer, stored in ptr variable, and advance segmented buffer
|
||||
offset by chunk_len
|
||||
|
||||
*/
|
||||
OPJ_BOOL opj_seg_buf_zero_copy_read(opj_seg_buf_t* seg_buf,
|
||||
OPJ_BYTE** ptr,
|
||||
OPJ_SIZE_T chunk_len);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -1210,7 +1210,7 @@ static OPJ_BOOL opj_t1_allocate_buffers(
|
|||
* and initializes the look-up tables of the Tier-1 coder/decoder
|
||||
* @return a new T1 handle if successful, returns NULL otherwise
|
||||
*/
|
||||
opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder)
|
||||
opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder, OPJ_UINT16 code_block_width, OPJ_UINT16 code_block_height)
|
||||
{
|
||||
opj_t1_t *l_t1 = 00;
|
||||
|
||||
|
@ -1231,6 +1231,16 @@ opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder)
|
|||
opj_t1_destroy(l_t1);
|
||||
return 00;
|
||||
}
|
||||
|
||||
if (!isEncoder && code_block_width > 0 && code_block_height > 0) {
|
||||
l_t1->compressed_block = (OPJ_BYTE*)opj_malloc(code_block_width * code_block_height);
|
||||
if (!l_t1->compressed_block) {
|
||||
opj_t1_destroy(l_t1);
|
||||
return 00;
|
||||
}
|
||||
l_t1->compressed_block_size = (OPJ_SIZE_T)(code_block_width * code_block_height);
|
||||
|
||||
}
|
||||
l_t1->encoder = isEncoder;
|
||||
|
||||
return l_t1;
|
||||
|
@ -1264,7 +1274,8 @@ void opj_t1_destroy(opj_t1_t *p_t1)
|
|||
opj_aligned_free(p_t1->flags);
|
||||
p_t1->flags = 00;
|
||||
}
|
||||
|
||||
if (p_t1->compressed_block)
|
||||
opj_free(p_t1->compressed_block);
|
||||
opj_free(p_t1);
|
||||
}
|
||||
|
||||
|
@ -1371,6 +1382,8 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
|
|||
OPJ_UINT32 passtype;
|
||||
OPJ_UINT32 segno, passno;
|
||||
OPJ_BYTE type = T1_TYPE_MQ; /* BYPASS mode */
|
||||
OPJ_BYTE* block_buffer = NULL;
|
||||
OPJ_SIZE_T total_seg_len;
|
||||
|
||||
if(!opj_t1_allocate_buffers(
|
||||
t1,
|
||||
|
@ -1380,6 +1393,33 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
|
|||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
total_seg_len = opj_min_buf_vec_get_len(&cblk->seg_buffers);
|
||||
if (cblk->real_num_segs && total_seg_len) {
|
||||
/* if there is only one segment, then it is already contiguous, so no need to make a copy*/
|
||||
if (total_seg_len == 1 && cblk->seg_buffers.data[0]) {
|
||||
block_buffer = ((opj_buf_t*)(cblk->seg_buffers.data[0]))->buf;
|
||||
}
|
||||
else {
|
||||
/* block should have been allocated on creation of t1*/
|
||||
if (!t1->compressed_block)
|
||||
return OPJ_FALSE;
|
||||
if (t1->compressed_block_size < total_seg_len) {
|
||||
OPJ_BYTE* new_block = opj_realloc(t1->compressed_block, total_seg_len);
|
||||
if (!new_block)
|
||||
return OPJ_FALSE;
|
||||
t1->compressed_block = new_block;
|
||||
t1->compressed_block_size = total_seg_len;
|
||||
}
|
||||
opj_min_buf_vec_copy_to_contiguous_buffer(&cblk->seg_buffers, t1->compressed_block);
|
||||
block_buffer = t1->compressed_block;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bpno_plus_one = (OPJ_INT32)(roishift + cblk->numbps);
|
||||
passtype = 2;
|
||||
|
||||
|
@ -1393,14 +1433,10 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
|
|||
|
||||
/* BYPASS mode */
|
||||
type = ((bpno_plus_one <= ((OPJ_INT32) (cblk->numbps)) - 4) && (passtype < 2) && (cblksty & J2K_CCP_CBLKSTY_LAZY)) ? T1_TYPE_RAW : T1_TYPE_MQ;
|
||||
/* FIXME: slviewer gets here with a null pointer. Why? Partially downloaded and/or corrupt textures? */
|
||||
if(seg->data == 00){
|
||||
continue;
|
||||
}
|
||||
if (type == T1_TYPE_RAW) {
|
||||
opj_raw_init_dec(raw, (*seg->data) + seg->dataindex, seg->len);
|
||||
opj_raw_init_dec(raw, block_buffer + seg->dataindex, seg->len);
|
||||
} else {
|
||||
if (OPJ_FALSE == opj_mqc_init_dec(mqc, (*seg->data) + seg->dataindex, seg->len)) {
|
||||
if (OPJ_FALSE == opj_mqc_init_dec(mqc, block_buffer + seg->dataindex, seg->len)) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,8 @@ typedef OPJ_INT16 opj_flag_t;
|
|||
Tier-1 coding (coding of code-block coefficients)
|
||||
*/
|
||||
typedef struct opj_t1 {
|
||||
|
||||
OPJ_BYTE* compressed_block;
|
||||
OPJ_SIZE_T compressed_block_size;
|
||||
/** MQC component */
|
||||
opj_mqc_t *mqc;
|
||||
/** RAW component */
|
||||
|
@ -151,7 +152,7 @@ OPJ_BOOL opj_t1_decode_cblks( opj_t1_t* t1,
|
|||
* and initializes the look-up tables of the Tier-1 coder/decoder
|
||||
* @return a new T1 handle if successful, returns NULL otherwise
|
||||
*/
|
||||
opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder);
|
||||
opj_t1_t* opj_t1_create(OPJ_BOOL isEncoder, OPJ_UINT16 code_block_width, OPJ_UINT16 code_block_height);
|
||||
|
||||
/**
|
||||
* Destroys a previously created T1 handle
|
||||
|
|
|
@ -94,9 +94,8 @@ 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_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * data_read,
|
||||
OPJ_UINT32 max_length,
|
||||
opj_packet_info_t *pack_info,
|
||||
opj_event_mgr_t *p_manager);
|
||||
|
||||
|
@ -104,9 +103,8 @@ 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_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * p_data_read,
|
||||
OPJ_UINT32 p_max_length,
|
||||
opj_packet_info_t *p_pack_info,
|
||||
opj_event_mgr_t *p_manager);
|
||||
|
||||
|
@ -115,18 +113,16 @@ static OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2,
|
|||
opj_tcp_t *p_tcp,
|
||||
opj_pi_iterator_t *p_pi,
|
||||
OPJ_BOOL * p_is_data_present,
|
||||
OPJ_BYTE *p_src_data,
|
||||
opj_seg_buf_t* src_buf,
|
||||
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_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * p_data_read,
|
||||
OPJ_UINT32 p_max_length,
|
||||
opj_packet_info_t *pack_info,
|
||||
opj_event_mgr_t *p_manager);
|
||||
|
||||
|
@ -347,13 +343,11 @@ static void opj_null_jas_fprintf(FILE* file, const char * format, ...)
|
|||
OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2,
|
||||
OPJ_UINT32 p_tile_no,
|
||||
opj_tcd_tile_t *p_tile,
|
||||
OPJ_BYTE *p_src,
|
||||
opj_seg_buf_t* src_buf,
|
||||
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;
|
||||
|
@ -419,7 +413,9 @@ OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2,
|
|||
|
||||
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)) {
|
||||
if (! opj_t2_decode_packet(p_t2,p_tile,l_tcp,l_current_pi,
|
||||
src_buf,&l_nb_bytes_read,
|
||||
l_pack_info, p_manager)) {
|
||||
opj_pi_destroy(l_pi,l_nb_pocs);
|
||||
opj_free(first_pass_failed);
|
||||
return OPJ_FALSE;
|
||||
|
@ -430,7 +426,10 @@ OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2,
|
|||
}
|
||||
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)) {
|
||||
if (! opj_t2_skip_packet(p_t2,p_tile,l_tcp,l_current_pi,
|
||||
src_buf,
|
||||
&l_nb_bytes_read,
|
||||
l_pack_info, p_manager)) {
|
||||
opj_pi_destroy(l_pi,l_nb_pocs);
|
||||
opj_free(first_pass_failed);
|
||||
return OPJ_FALSE;
|
||||
|
@ -443,8 +442,8 @@ OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2,
|
|||
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;
|
||||
*p_data_read += l_nb_bytes_read;
|
||||
|
||||
|
||||
/* INDEX >> */
|
||||
#ifdef TODO_MSD
|
||||
|
@ -484,7 +483,6 @@ OPJ_BOOL opj_t2_decode_packets( opj_t2_t *p_t2,
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -521,9 +519,8 @@ 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_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * p_data_read,
|
||||
OPJ_UINT32 p_max_length,
|
||||
opj_packet_info_t *p_pack_info,
|
||||
opj_event_mgr_t *p_manager)
|
||||
{
|
||||
|
@ -533,22 +530,24 @@ static OPJ_BOOL opj_t2_decode_packet( opj_t2_t* p_t2,
|
|||
|
||||
*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)) {
|
||||
if (! opj_t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,
|
||||
src_buf,
|
||||
&l_nb_bytes_read,
|
||||
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)) {
|
||||
if (! opj_t2_read_packet_data(p_t2,p_tile,p_pi,
|
||||
src_buf,&l_nb_bytes_read,
|
||||
p_pack_info, p_manager)) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
l_nb_total_bytes_read += l_nb_bytes_read;
|
||||
}
|
||||
|
||||
|
@ -797,37 +796,42 @@ 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_seg_buf_t* src_buf,
|
||||
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;
|
||||
OPJ_UINT32 p_max_length = (OPJ_UINT32)opj_seg_buf_get_cur_seg_len(src_buf);
|
||||
|
||||
*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)) {
|
||||
if (! opj_t2_read_packet_header(p_t2,p_tile,p_tcp,p_pi,&l_read_data,
|
||||
src_buf,
|
||||
&l_nb_bytes_read,
|
||||
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;
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
opj_seg_buf_incr_cur_seg_offset(src_buf, l_nb_bytes_read);
|
||||
l_nb_total_bytes_read += l_nb_bytes_read;
|
||||
}
|
||||
*p_data_read = l_nb_total_bytes_read;
|
||||
|
||||
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
@ -838,13 +842,14 @@ static OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2,
|
|||
opj_tcp_t *p_tcp,
|
||||
opj_pi_iterator_t *p_pi,
|
||||
OPJ_BOOL * p_is_data_present,
|
||||
OPJ_BYTE *p_src_data,
|
||||
opj_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * p_data_read,
|
||||
OPJ_UINT32 p_max_length,
|
||||
opj_packet_info_t *p_pack_info,
|
||||
opj_event_mgr_t *p_manager)
|
||||
|
||||
{
|
||||
OPJ_BYTE *p_src_data = opj_seg_buf_get_global_ptr(src_buf);
|
||||
OPJ_UINT32 p_max_length = (OPJ_UINT32)opj_seg_buf_get_cur_seg_len(src_buf);
|
||||
/* loop */
|
||||
OPJ_UINT32 bandno, cblkno;
|
||||
OPJ_UINT32 l_nb_code_blocks;
|
||||
|
@ -966,6 +971,7 @@ static OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2,
|
|||
|
||||
* p_is_data_present = OPJ_FALSE;
|
||||
*p_data_read = (OPJ_UINT32)(l_current_data - p_src_data);
|
||||
opj_seg_buf_incr_cur_seg_offset(src_buf, *p_data_read);
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1096,6 +1102,7 @@ static OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2,
|
|||
|
||||
*p_is_data_present = OPJ_TRUE;
|
||||
*p_data_read = (OPJ_UINT32)(l_current_data - p_src_data);
|
||||
opj_seg_buf_incr_cur_seg_offset(src_buf, *p_data_read);
|
||||
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
@ -1103,15 +1110,13 @@ static OPJ_BOOL opj_t2_read_packet_header( opj_t2_t* p_t2,
|
|||
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_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * p_data_read,
|
||||
OPJ_UINT32 p_max_length,
|
||||
opj_packet_info_t *pack_info,
|
||||
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];
|
||||
|
@ -1155,10 +1160,12 @@ static OPJ_BOOL opj_t2_read_packet_data( opj_t2_t* p_t2,
|
|||
}
|
||||
|
||||
do {
|
||||
OPJ_OFF_T offset = opj_seg_buf_get_global_offset(src_buf);
|
||||
OPJ_SIZE_T len = src_buf->data_len;
|
||||
/* 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)) {
|
||||
if ((((OPJ_SIZE_T)offset + (OPJ_SIZE_T)l_seg->newlen) > (OPJ_SIZE_T)len)) {
|
||||
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);
|
||||
l_seg->newlen, len, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
||||
|
@ -1187,6 +1194,7 @@ static OPJ_BOOL opj_t2_read_packet_data( opj_t2_t* p_t2,
|
|||
l_seg->newlen, l_cblk->data_current_size, 0xFFFFFFFF - l_seg->newlen, cblkno, p_pi->precno, bandno, p_pi->resno, p_pi->compno);
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
#ifdef POO
|
||||
/* Check if the cblk->data have allocated enough memory */
|
||||
if ((l_cblk->data_current_size + l_seg->newlen) > l_cblk->data_max_size) {
|
||||
OPJ_BYTE* new_cblk_data = (OPJ_BYTE*) opj_realloc(l_cblk->data, l_cblk->data_current_size + l_seg->newlen);
|
||||
|
@ -1201,15 +1209,19 @@ static OPJ_BOOL opj_t2_read_packet_data( opj_t2_t* p_t2,
|
|||
l_cblk->data = new_cblk_data;
|
||||
}
|
||||
|
||||
memcpy(l_cblk->data + l_cblk->data_current_size, l_current_data, l_seg->newlen);
|
||||
|
||||
memcpy(l_cblk->data + l_cblk->data_current_size, src_buf->mother.buf + src_buf->mother.offset, l_seg->newlen);
|
||||
#endif
|
||||
if (l_seg->numpasses == 0) {
|
||||
l_seg->data = &l_cblk->data;
|
||||
l_seg->dataindex = l_cblk->data_current_size;
|
||||
l_seg->dataindex = l_cblk->data_current_size;
|
||||
}
|
||||
|
||||
l_current_data += l_seg->newlen;
|
||||
l_seg->numpasses += l_seg->numnewpasses;
|
||||
opj_min_buf_vec_push_back(&l_cblk->seg_buffers, opj_seg_buf_get_global_ptr(src_buf), l_seg->newlen);
|
||||
|
||||
|
||||
|
||||
*(p_data_read) += l_seg->newlen;
|
||||
opj_seg_buf_incr_cur_seg_offset(src_buf, l_seg->newlen);
|
||||
l_seg->numpasses += l_seg->numnewpasses;
|
||||
l_cblk->numnewpasses -= l_seg->numnewpasses;
|
||||
|
||||
l_seg->real_num_passes = l_seg->numpasses;
|
||||
|
@ -1228,10 +1240,6 @@ static OPJ_BOOL opj_t2_read_packet_data( opj_t2_t* p_t2,
|
|||
|
||||
++l_band;
|
||||
}
|
||||
|
||||
*(p_data_read) = (OPJ_UINT32)(l_current_data - p_src_data);
|
||||
|
||||
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,9 +105,8 @@ Decode the packets of a tile from a source buffer
|
|||
OPJ_BOOL opj_t2_decode_packets( opj_t2_t *t2,
|
||||
OPJ_UINT32 tileno,
|
||||
opj_tcd_tile_t *tile,
|
||||
OPJ_BYTE *src,
|
||||
opj_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * p_data_read,
|
||||
OPJ_UINT32 len,
|
||||
opj_codestream_index_t *cstr_info,
|
||||
opj_event_mgr_t *p_manager);
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ void tcd_dump(FILE *fd, opj_tcd_t *tcd, opj_tcd_image_t * img) {
|
|||
static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no, OPJ_BOOL isEncoder, OPJ_FLOAT32 fraction, OPJ_SIZE_T sizeof_block, opj_event_mgr_t* manager);
|
||||
|
||||
/**
|
||||
* Allocates memory for a decoding code block.
|
||||
* Allocates memory for a decoding code block (but not data)
|
||||
*/
|
||||
static OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block);
|
||||
|
||||
|
@ -143,9 +143,8 @@ static void opj_tcd_free_tile(opj_tcd_t *tcd);
|
|||
|
||||
|
||||
static OPJ_BOOL opj_tcd_t2_decode ( opj_tcd_t *p_tcd,
|
||||
OPJ_BYTE * p_src_data,
|
||||
opj_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * p_data_read,
|
||||
OPJ_UINT32 p_max_src_size,
|
||||
opj_codestream_index_t *p_cstr_index,
|
||||
opj_event_mgr_t *p_manager);
|
||||
|
||||
|
@ -695,6 +694,8 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
|
|||
l_image = p_tcd->image;
|
||||
l_image_comp = p_tcd->image->comps;
|
||||
|
||||
opj_seg_buf_rewind(&l_tcp->m_data);
|
||||
|
||||
p = p_tile_no % l_cp->tw; /* tile coordinates */
|
||||
q = p_tile_no / l_cp->tw;
|
||||
/*fprintf(stderr, "Tile coordinate = %d,%d\n", p, q);*/
|
||||
|
@ -1091,42 +1092,36 @@ static OPJ_BOOL opj_tcd_code_block_enc_allocate_data (opj_tcd_cblk_enc_t * p_cod
|
|||
}
|
||||
|
||||
/**
|
||||
* Allocates memory for a decoding code block.
|
||||
* Allocates memory for a decoding code block (but not data)
|
||||
*/
|
||||
static OPJ_BOOL opj_tcd_code_block_dec_allocate (opj_tcd_cblk_dec_t * p_code_block)
|
||||
{
|
||||
if (! p_code_block->data) {
|
||||
if (!p_code_block->segs) {
|
||||
p_code_block->segs = (opj_tcd_seg_t *)opj_calloc(OPJ_J2K_DEFAULT_NB_SEGS, sizeof(opj_tcd_seg_t));
|
||||
if (!p_code_block->segs) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
/*fprintf(stderr, "Allocate %d elements of code_block->data\n", OPJ_J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));*/
|
||||
|
||||
p_code_block->data = (OPJ_BYTE*) opj_malloc(OPJ_J2K_DEFAULT_CBLK_DATA_SIZE);
|
||||
if (! p_code_block->data) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
p_code_block->data_max_size = OPJ_J2K_DEFAULT_CBLK_DATA_SIZE;
|
||||
/*fprintf(stderr, "Allocate 8192 elements of code_block->data\n");*/
|
||||
p_code_block->m_current_max_segs = OPJ_J2K_DEFAULT_NB_SEGS;
|
||||
|
||||
p_code_block->segs = (opj_tcd_seg_t *) opj_calloc(OPJ_J2K_DEFAULT_NB_SEGS,sizeof(opj_tcd_seg_t));
|
||||
if (! p_code_block->segs) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
/*fprintf(stderr, "Allocate %d elements of code_block->data\n", OPJ_J2K_DEFAULT_NB_SEGS * sizeof(opj_tcd_seg_t));*/
|
||||
/*fprintf(stderr, "Allocate 8192 elements of code_block->data\n");*/
|
||||
/*fprintf(stderr, "m_current_max_segs of code_block->data = %d\n", p_code_block->m_current_max_segs);*/
|
||||
}
|
||||
else {
|
||||
/* sanitize */
|
||||
opj_tcd_seg_t * l_segs = p_code_block->segs;
|
||||
OPJ_UINT32 l_current_max_segs = p_code_block->m_current_max_segs;
|
||||
|
||||
p_code_block->m_current_max_segs = OPJ_J2K_DEFAULT_NB_SEGS;
|
||||
/*fprintf(stderr, "m_current_max_segs of code_block->data = %d\n", p_code_block->m_current_max_segs);*/
|
||||
} else {
|
||||
/* sanitize */
|
||||
OPJ_BYTE* l_data = p_code_block->data;
|
||||
OPJ_UINT32 l_data_max_size = p_code_block->data_max_size;
|
||||
opj_tcd_seg_t * l_segs = p_code_block->segs;
|
||||
OPJ_UINT32 l_current_max_segs = p_code_block->m_current_max_segs;
|
||||
/* Note: since seg_buffers simply holds references to another data buffer,
|
||||
we do not need to copy it to the sanitized block */
|
||||
opj_vec_cleanup(&p_code_block->seg_buffers);
|
||||
|
||||
memset(p_code_block, 0, sizeof(opj_tcd_cblk_dec_t));
|
||||
p_code_block->data = l_data;
|
||||
p_code_block->data_max_size = l_data_max_size;
|
||||
p_code_block->segs = l_segs;
|
||||
p_code_block->m_current_max_segs = l_current_max_segs;
|
||||
}
|
||||
|
||||
return OPJ_TRUE;
|
||||
memset(p_code_block, 0, sizeof(opj_tcd_cblk_dec_t));
|
||||
p_code_block->segs = l_segs;
|
||||
p_code_block->m_current_max_segs = l_current_max_segs;
|
||||
}
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
OPJ_UINT32 opj_tcd_get_decoded_tile_size ( opj_tcd_t *p_tcd )
|
||||
|
@ -1251,8 +1246,7 @@ OPJ_BOOL opj_tcd_encode_tile( opj_tcd_t *p_tcd,
|
|||
}
|
||||
|
||||
OPJ_BOOL opj_tcd_decode_tile( opj_tcd_t *p_tcd,
|
||||
OPJ_BYTE *p_src,
|
||||
OPJ_UINT32 p_max_length,
|
||||
opj_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 p_tile_no,
|
||||
opj_codestream_index_t *p_cstr_index,
|
||||
opj_event_mgr_t *p_manager
|
||||
|
@ -1288,7 +1282,7 @@ OPJ_BOOL opj_tcd_decode_tile( opj_tcd_t *p_tcd,
|
|||
/*--------------TIER2------------------*/
|
||||
/* FIXME _ProfStart(PGROUP_T2); */
|
||||
l_data_read = 0;
|
||||
if (! opj_tcd_t2_decode(p_tcd, p_src, &l_data_read, p_max_length, p_cstr_index, p_manager))
|
||||
if (! opj_tcd_t2_decode(p_tcd, src_buf, &l_data_read,p_cstr_index, p_manager))
|
||||
{
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
@ -1535,9 +1529,8 @@ static void opj_tcd_free_tile(opj_tcd_t *p_tcd)
|
|||
|
||||
|
||||
static OPJ_BOOL opj_tcd_t2_decode (opj_tcd_t *p_tcd,
|
||||
OPJ_BYTE * p_src_data,
|
||||
opj_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 * p_data_read,
|
||||
OPJ_UINT32 p_max_src_size,
|
||||
opj_codestream_index_t *p_cstr_index,
|
||||
opj_event_mgr_t *p_manager
|
||||
)
|
||||
|
@ -1553,9 +1546,8 @@ static OPJ_BOOL opj_tcd_t2_decode (opj_tcd_t *p_tcd,
|
|||
l_t2,
|
||||
p_tcd->tcd_tileno,
|
||||
p_tcd->tcd_image->tiles,
|
||||
p_src_data,
|
||||
src_buf,
|
||||
p_data_read,
|
||||
p_max_src_size,
|
||||
p_cstr_index,
|
||||
p_manager)) {
|
||||
opj_t2_destroy(l_t2);
|
||||
|
@ -1576,8 +1568,7 @@ static OPJ_BOOL opj_tcd_t1_decode ( opj_tcd_t *p_tcd )
|
|||
opj_tcd_tilecomp_t* l_tile_comp = l_tile->comps;
|
||||
opj_tccp_t * l_tccp = p_tcd->tcp->tccps;
|
||||
|
||||
|
||||
l_t1 = opj_t1_create(OPJ_FALSE);
|
||||
l_t1 = opj_t1_create(OPJ_FALSE, l_tccp->cblkw, l_tccp->cblkh);
|
||||
if (l_t1 == 00) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
@ -1801,12 +1792,7 @@ static void opj_tcd_code_block_dec_deallocate (opj_tcd_precinct_t * p_precinct)
|
|||
/*fprintf(stderr,"nb_code_blocks =%d\t}\n", l_nb_code_blocks);*/
|
||||
|
||||
for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) {
|
||||
|
||||
if (l_code_block->data) {
|
||||
opj_free(l_code_block->data);
|
||||
l_code_block->data = 00;
|
||||
}
|
||||
|
||||
opj_vec_cleanup(&l_code_block->seg_buffers);
|
||||
if (l_code_block->segs) {
|
||||
opj_free(l_code_block->segs );
|
||||
l_code_block->segs = 00;
|
||||
|
@ -2012,7 +1998,7 @@ static OPJ_BOOL opj_tcd_t1_encode ( opj_tcd_t *p_tcd )
|
|||
OPJ_UINT32 l_mct_numcomps = 0U;
|
||||
opj_tcp_t * l_tcp = p_tcd->tcp;
|
||||
|
||||
l_t1 = opj_t1_create(OPJ_TRUE);
|
||||
l_t1 = opj_t1_create(OPJ_TRUE,0,0);
|
||||
if (l_t1 == 00) {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,6 @@ each other. The functions in TCD.C are used by other functions in J2K.C.
|
|||
FIXME DOC
|
||||
*/
|
||||
typedef struct opj_tcd_seg {
|
||||
OPJ_BYTE ** data;
|
||||
OPJ_UINT32 dataindex;
|
||||
OPJ_UINT32 numpasses;
|
||||
OPJ_UINT32 real_num_passes;
|
||||
|
@ -101,7 +100,7 @@ typedef struct opj_tcd_cblk_enc {
|
|||
|
||||
|
||||
typedef struct opj_tcd_cblk_dec {
|
||||
OPJ_BYTE * data; /* Data */
|
||||
opj_vec_t seg_buffers;
|
||||
opj_tcd_seg_t* segs; /* segments information */
|
||||
OPJ_INT32 x0, y0, x1, y1; /* position of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
|
||||
OPJ_UINT32 numbps;
|
||||
|
@ -316,8 +315,7 @@ Decode a tile from a buffer into a raw image
|
|||
@param manager the event manager.
|
||||
*/
|
||||
OPJ_BOOL opj_tcd_decode_tile( opj_tcd_t *tcd,
|
||||
OPJ_BYTE *src,
|
||||
OPJ_UINT32 len,
|
||||
opj_seg_buf_t* src_buf,
|
||||
OPJ_UINT32 tileno,
|
||||
opj_codestream_index_t *cstr_info,
|
||||
opj_event_mgr_t *manager);
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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) 2015, Aaron Boxer
|
||||
* 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"
|
||||
|
||||
const OPJ_INT32 VECTOR_INITIAL_CAPACITY = 4;
|
||||
|
||||
|
||||
static OPJ_BOOL opj_vec_double_capacity_if_full(opj_vec_t *vec) {
|
||||
if (!vec)
|
||||
return OPJ_FALSE;
|
||||
if (vec->size == vec->capacity-1) {
|
||||
void** new_data = NULL;
|
||||
OPJ_INT32 new_capacity = (OPJ_INT32)(1.5*vec->capacity);
|
||||
new_data = opj_realloc(vec->data, (OPJ_SIZE_T)(sizeof(void*) * new_capacity));
|
||||
if (new_data) {
|
||||
vec->capacity = new_capacity;
|
||||
vec->data = new_data;
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
else {
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
}
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
OPJ_BOOL opj_vec_init(opj_vec_t *vec) {
|
||||
if (!vec)
|
||||
return OPJ_FALSE;
|
||||
if (vec->data)
|
||||
return OPJ_TRUE;
|
||||
|
||||
vec->size = 0;
|
||||
vec->capacity = VECTOR_INITIAL_CAPACITY;
|
||||
vec->data = opj_malloc(sizeof(void*) * vec->capacity);
|
||||
return vec->data ? OPJ_TRUE : OPJ_FALSE;
|
||||
}
|
||||
|
||||
OPJ_BOOL opj_vec_push_back(opj_vec_t *vec, void* value) {
|
||||
if (!opj_vec_double_capacity_if_full(vec))
|
||||
return OPJ_FALSE;
|
||||
vec->data[vec->size++] = value;
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
void* opj_vec_get(opj_vec_t *vec, OPJ_INT32 index) {
|
||||
if (!vec->data)
|
||||
return NULL;
|
||||
assert(index < vec->size && index >= 0);
|
||||
if (index >= vec->size || index < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return vec->data[index];
|
||||
}
|
||||
|
||||
void* opj_vec_back(opj_vec_t *vec) {
|
||||
if (!vec || !vec->data || !vec->size)
|
||||
return NULL;
|
||||
return opj_vec_get(vec, vec->size - 1);
|
||||
}
|
||||
|
||||
OPJ_BOOL opj_vec_set(opj_vec_t *vec, OPJ_INT32 index, void* value) {
|
||||
if (!vec)
|
||||
return OPJ_FALSE;
|
||||
while (index >= vec->size) {
|
||||
if (!opj_vec_push_back(vec, NULL))
|
||||
return OPJ_FALSE;
|
||||
}
|
||||
vec->data[index] = value;
|
||||
return OPJ_TRUE;
|
||||
}
|
||||
|
||||
void opj_vec_cleanup(opj_vec_t *vec) {
|
||||
OPJ_INT32 i;
|
||||
if (!vec || !vec->data)
|
||||
return;
|
||||
|
||||
if (vec->owns_data) {
|
||||
for (i = 0; i < vec->size; ++i) {
|
||||
if (vec->data[i])
|
||||
opj_free(vec->data[i]);
|
||||
}
|
||||
}
|
||||
opj_free(vec->data);
|
||||
vec->data = NULL;
|
||||
vec->size = 0;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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) 2015, Aaron Boxer
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __VECTOR_H
|
||||
#define __VECTOR_H
|
||||
|
||||
/*
|
||||
Vector - a dynamic array.
|
||||
|
||||
*/
|
||||
|
||||
typedef struct opj_vec{
|
||||
OPJ_INT32 size; /* current size of vec */
|
||||
OPJ_INT32 capacity; /* maximum size of vec */
|
||||
void* *data; /* array of void* pointers */
|
||||
OPJ_BOOL owns_data;
|
||||
} opj_vec_t;
|
||||
|
||||
/*
|
||||
Initialize vector
|
||||
*/
|
||||
OPJ_BOOL opj_vec_init(opj_vec_t *vec);
|
||||
|
||||
/*
|
||||
Add a value to the end of the vector
|
||||
*/
|
||||
OPJ_BOOL opj_vec_push_back(opj_vec_t *vec, void* value);
|
||||
|
||||
/*
|
||||
Set a value at specified index. If index is greater then the size of the vector,
|
||||
all intervening indices will be initialized to NULL
|
||||
*/
|
||||
OPJ_BOOL opj_vec_set(opj_vec_t *vec, OPJ_INT32 index, void* value);
|
||||
|
||||
/*
|
||||
Get value at specified index
|
||||
*/
|
||||
void* opj_vec_get(opj_vec_t *vec, OPJ_INT32 index);
|
||||
|
||||
/*
|
||||
Get value at end of vector
|
||||
*/
|
||||
void* opj_vec_back(opj_vec_t *vec);
|
||||
|
||||
/*
|
||||
Clean up vector resources. Does NOT free vector itself
|
||||
*/
|
||||
void opj_vec_cleanup(opj_vec_t *vec);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue