summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2021-06-07 15:16:53 +0200
committerEven Rouault <even.rouault@spatialys.com>2021-06-07 15:49:08 +0200
commita36ae0386066c9ddd089788930be5a42a176446e (patch)
tree8effed4d892faee90d8ea96c6c15030ed6953614 /src/lib
parent2624908517ac0489ff1b5471f423dfe84d79da08 (diff)
Add support for enabling generation of TLM markers in encoder
Support was already there, but restricted to Cinema and IMF profiles, and 255 tiles * Add -TLM switch added to opj_compress * Make opj_encoder_set_extra_options() function accept a TLM=YES option.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/openjp2/j2k.c77
-rw-r--r--src/lib/openjp2/j2k.h6
-rw-r--r--src/lib/openjp2/openjpeg.h7
3 files changed, 73 insertions, 17 deletions
diff --git a/src/lib/openjp2/j2k.c b/src/lib/openjp2/j2k.c
index 8e343ab2..1f064c31 100644
--- a/src/lib/openjp2/j2k.c
+++ b/src/lib/openjp2/j2k.c
@@ -910,9 +910,15 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
static void opj_j2k_update_tlm(opj_j2k_t * p_j2k, OPJ_UINT32 p_tile_part_size)
{
- opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,
- p_j2k->m_current_tile_number, 1); /* PSOT */
- ++p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current;
+ if (p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte) {
+ opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,
+ p_j2k->m_current_tile_number, 1);
+ p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 1;
+ } else {
+ opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,
+ p_j2k->m_current_tile_number, 2);
+ p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current += 2;
+ }
opj_write_bytes(p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_current,
p_tile_part_size, 4); /* PSOT */
@@ -4170,13 +4176,33 @@ static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k,
{
OPJ_BYTE * l_current_data = 00;
OPJ_UINT32 l_tlm_size;
+ OPJ_UINT32 size_per_tile_part;
/* preconditions */
assert(p_j2k != 00);
assert(p_manager != 00);
assert(p_stream != 00);
- l_tlm_size = 6 + (5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts);
+ /* 10921 = (65535 - header_size) / size_per_tile_part where */
+ /* header_size = 4 and size_per_tile_part = 6 */
+ if (p_j2k->m_specific_param.m_encoder.m_total_tile_parts > 10921) {
+ /* We could do more but it would require writing several TLM markers */
+ opj_event_msg(p_manager, EVT_ERROR,
+ "A maximum of 10921 tile-parts are supported currently "
+ "when writing TLM marker\n");
+ return OPJ_FALSE;
+ }
+
+ if (p_j2k->m_specific_param.m_encoder.m_total_tile_parts <= 255) {
+ size_per_tile_part = 5;
+ p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte = OPJ_TRUE;
+ } else {
+ size_per_tile_part = 6;
+ p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte = OPJ_FALSE;
+ }
+
+ l_tlm_size = 2 + 4 + (size_per_tile_part *
+ p_j2k->m_specific_param.m_encoder.m_total_tile_parts);
if (l_tlm_size > p_j2k->m_specific_param.m_encoder.m_header_tile_data_size) {
OPJ_BYTE *new_header_tile_data = (OPJ_BYTE *) opj_realloc(
@@ -4191,6 +4217,7 @@ static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k,
p_j2k->m_specific_param.m_encoder.m_header_tile_data = new_header_tile_data;
p_j2k->m_specific_param.m_encoder.m_header_tile_data_size = l_tlm_size;
}
+ memset(p_j2k->m_specific_param.m_encoder.m_header_tile_data, 0, l_tlm_size);
l_current_data = p_j2k->m_specific_param.m_encoder.m_header_tile_data;
@@ -4210,11 +4237,14 @@ static OPJ_BOOL opj_j2k_write_tlm(opj_j2k_t *p_j2k,
1); /* Ztlm=0*/
++l_current_data;
- opj_write_bytes(l_current_data, 0x50,
- 1); /* Stlm ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */
+ /* Stlm 0x50= ST=1(8bits-255 tiles max),SP=1(Ptlm=32bits) */
+ /* Stlm 0x60= ST=2(16bits-65535 tiles max),SP=1(Ptlm=32bits) */
+ opj_write_bytes(l_current_data,
+ size_per_tile_part == 5 ? 0x50 : 0x60,
+ 1);
++l_current_data;
- /* do nothing on the 5 * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */
+ /* do nothing on the size_per_tile_part * l_j2k->m_specific_param.m_encoder.m_total_tile_parts remaining data */
if (opj_stream_write_data(p_stream,
p_j2k->m_specific_param.m_encoder.m_header_tile_data, l_tlm_size,
p_manager) != l_tlm_size) {
@@ -5354,9 +5384,9 @@ static OPJ_BOOL opj_j2k_update_rates(opj_j2k_t *p_j2k,
return OPJ_FALSE;
}
- if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
+ if (p_j2k->m_specific_param.m_encoder.m_TLM) {
p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer =
- (OPJ_BYTE *) opj_malloc(5 *
+ (OPJ_BYTE *) opj_malloc(6 *
p_j2k->m_specific_param.m_encoder.m_total_tile_parts);
if (! p_j2k->m_specific_param.m_encoder.m_tlm_sot_offsets_buffer) {
return OPJ_FALSE;
@@ -7709,6 +7739,10 @@ OPJ_BOOL opj_j2k_setup_encoder(opj_j2k_t *p_j2k,
}
}
+ if (OPJ_IS_CINEMA(parameters->rsiz) || OPJ_IS_IMF(parameters->rsiz)) {
+ p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE;
+ }
+
/* Manage profiles and applications and set RSIZ */
/* set cinema parameters if required */
if (OPJ_IS_CINEMA(parameters->rsiz)) {
@@ -12048,6 +12082,16 @@ OPJ_BOOL opj_j2k_encoder_set_extra_options(
"Invalid value for option: %s.\n", *p_option_iter);
return OPJ_FALSE;
}
+ } else if (strncmp(*p_option_iter, "TLM=", 4) == 0) {
+ if (strcmp(*p_option_iter, "TLM=YES") == 0) {
+ p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_TRUE;
+ } else if (strcmp(*p_option_iter, "TLM=NO") == 0) {
+ p_j2k->m_specific_param.m_encoder.m_TLM = OPJ_FALSE;
+ } else {
+ opj_event_msg(p_manager, EVT_ERROR,
+ "Invalid value for option: %s.\n", *p_option_iter);
+ return OPJ_FALSE;
+ }
} else {
opj_event_msg(p_manager, EVT_ERROR,
"Invalid option: %s.\n", *p_option_iter);
@@ -12445,7 +12489,7 @@ static OPJ_BOOL opj_j2k_setup_end_compress(opj_j2k_t *p_j2k,
return OPJ_FALSE;
}
- if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz) || OPJ_IS_IMF(p_j2k->m_cp.rsiz)) {
+ if (p_j2k->m_specific_param.m_encoder.m_TLM) {
if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,
(opj_procedure)opj_j2k_write_updated_tlm, p_manager)) {
return OPJ_FALSE;
@@ -12528,7 +12572,7 @@ static OPJ_BOOL opj_j2k_setup_header_writing(opj_j2k_t *p_j2k,
return OPJ_FALSE;
}
- if (OPJ_IS_CINEMA(p_j2k->m_cp.rsiz) || OPJ_IS_IMF(p_j2k->m_cp.rsiz)) {
+ if (p_j2k->m_specific_param.m_encoder.m_TLM) {
if (! opj_procedure_list_add_procedure(p_j2k->m_procedure_list,
(opj_procedure)opj_j2k_write_tlm, p_manager)) {
return OPJ_FALSE;
@@ -12661,7 +12705,7 @@ static OPJ_BOOL opj_j2k_write_first_tile_part(opj_j2k_t *p_j2k,
opj_write_bytes(l_begin_data + 6, l_nb_bytes_written,
4); /* PSOT */
- if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
+ if (p_j2k->m_specific_param.m_encoder.m_TLM) {
opj_j2k_update_tlm(p_j2k, l_nb_bytes_written);
}
@@ -12731,7 +12775,7 @@ static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k,
opj_write_bytes(l_begin_data + 6, l_part_tile_size,
4); /* PSOT */
- if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
+ if (p_j2k->m_specific_param.m_encoder.m_TLM) {
opj_j2k_update_tlm(p_j2k, l_part_tile_size);
}
@@ -12777,7 +12821,7 @@ static OPJ_BOOL opj_j2k_write_all_tile_parts(opj_j2k_t *p_j2k,
opj_write_bytes(l_begin_data + 6, l_part_tile_size,
4); /* PSOT */
- if (OPJ_IS_CINEMA(l_cp->rsiz) || OPJ_IS_IMF(l_cp->rsiz)) {
+ if (p_j2k->m_specific_param.m_encoder.m_TLM) {
opj_j2k_update_tlm(p_j2k, l_part_tile_size);
}
@@ -12796,13 +12840,16 @@ static OPJ_BOOL opj_j2k_write_updated_tlm(opj_j2k_t *p_j2k,
{
OPJ_UINT32 l_tlm_size;
OPJ_OFF_T l_tlm_position, l_current_position;
+ OPJ_UINT32 size_per_tile_part;
/* preconditions */
assert(p_j2k != 00);
assert(p_manager != 00);
assert(p_stream != 00);
- l_tlm_size = 5 * p_j2k->m_specific_param.m_encoder.m_total_tile_parts;
+ size_per_tile_part = p_j2k->m_specific_param.m_encoder.m_Ttlmi_is_byte ? 5 : 6;
+ l_tlm_size = size_per_tile_part *
+ p_j2k->m_specific_param.m_encoder.m_total_tile_parts;
l_tlm_position = 6 + p_j2k->m_specific_param.m_encoder.m_tlm_start;
l_current_position = opj_stream_tell(p_stream);
diff --git a/src/lib/openjp2/j2k.h b/src/lib/openjp2/j2k.h
index 9eb50b50..740ed9b6 100644
--- a/src/lib/openjp2/j2k.h
+++ b/src/lib/openjp2/j2k.h
@@ -503,6 +503,12 @@ typedef struct opj_j2k_enc {
/** Tile part number currently coding, taking into account POC. m_current_tile_part_number holds the total number of tile parts while encoding the last tile part.*/
OPJ_UINT32 m_current_tile_part_number; /*cur_tp_num */
+ /* whether to generate TLM markers */
+ OPJ_BOOL m_TLM;
+
+ /* whether the Ttlmi field in a TLM marker is a byte (otherwise a uint16) */
+ OPJ_BOOL m_Ttlmi_is_byte;
+
/**
locate the start position of the TLM marker
after encoding the tilepart, a jump (in j2k_write_sod) is done to the TLM marker to store the value of its length.
diff --git a/src/lib/openjp2/openjpeg.h b/src/lib/openjp2/openjpeg.h
index 269ac329..8829963f 100644
--- a/src/lib/openjp2/openjpeg.h
+++ b/src/lib/openjp2/openjpeg.h
@@ -1592,7 +1592,10 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec,
* <ul>
* <li>PLT=YES/NO. Defaults to NO. If set to YES, PLT marker segments,
* indicating the length of each packet in the tile-part header, will be
- * written. Since 2.3.2</li>
+ * written. Since 2.4.0</li>
+ * <li>TLM=YES/NO. Defaults to NO (except for Cinema and IMF profiles).
+ * If set to YES, TLM marker segments, indicating the length of each
+ * tile-part part will be written. Since 2.4.0</li>
* </ul>
*
* @param p_codec Compressor handle
@@ -1600,7 +1603,7 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_encoder(opj_codec_t *p_codec,
* array of strings. Each string is of the form KEY=VALUE.
*
* @return OPJ_TRUE in case of success.
- * @since 2.3.2
+ * @since 2.4.0
*/
OPJ_API OPJ_BOOL OPJ_CALLCONV opj_encoder_set_extra_options(
opj_codec_t *p_codec,