Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for partial bitstream decoding #1251

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
9 changes: 9 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.194.3/containers/cpp/.devcontainer/base.Dockerfile

# [Choice] Debian / Ubuntu version: debian-11, debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
ARG VARIANT="buster"
FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT}

# [Optional] Uncomment this section to install additional packages.
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# && apt-get -y install --no-install-recommends <your-package-list-here>
28 changes: 28 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.194.3/containers/cpp
{
"name": "C++",
"build": {
"dockerfile": "Dockerfile",
// Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
"args": { "VARIANT": "debian-10" }
},
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],

// Set *default* container specific settings.json values on container create.
"settings": {},

// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-vscode.cpptools"
],

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "gcc -v",

// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}
4 changes: 4 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
mkdir -p build
(cd build && cmake ..)
(cd build && make VERBOSE=1 -j ${nprocs})
3 changes: 1 addition & 2 deletions src/lib/openjp2/j2k.c
Original file line number Diff line number Diff line change
Expand Up @@ -4906,9 +4906,8 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
/* Check enough bytes left in stream before allocation */
if ((OPJ_OFF_T)p_j2k->m_specific_param.m_decoder.m_sot_length >
opj_stream_get_number_byte_left(p_stream)) {
opj_event_msg(p_manager, EVT_ERROR,
opj_event_msg(p_manager, EVT_WARNING,
"Tile part length size inconsistent with stream length\n");
return OPJ_FALSE;
}
if (p_j2k->m_specific_param.m_decoder.m_sot_length >
UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA) {
Expand Down
38 changes: 31 additions & 7 deletions src/lib/openjp2/t2.c
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,6 @@ OPJ_BOOL opj_t2_decode_packets(opj_tcd_t* tcd,
l_current_pi->precno, l_current_pi->layno, skip_packet ? "skipped" : "kept");
*/
}

if (!skip_packet) {
l_nb_bytes_read = 0;

Expand Down Expand Up @@ -1348,6 +1347,7 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
opj_tcd_cblk_dec_t* l_cblk = 00;
opj_tcd_resolution_t* l_res =
&p_tile->comps[p_pi->compno].resolutions[p_pi->resno];
OPJ_UINT32 partial_buffer = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OPJ_UINT32 partial_buffer = 0;
OPJ_BOOL partial_buffer = OPJ_FALSE;


OPJ_ARG_NOT_USED(p_t2);
OPJ_ARG_NOT_USED(pack_info);
Expand All @@ -1367,6 +1367,12 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) {
opj_tcd_seg_t *l_seg = 00;

// if we have a partial data stream, set numchunks to zero
// since we have no data to actually decode.
if(partial_buffer) {
l_cblk->numchunks = 0;
}

if (!l_cblk->numnewpasses) {
/* nothing to do */
++l_cblk;
Expand All @@ -1389,12 +1395,26 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
/* 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)) {
opj_event_msg(p_manager, EVT_ERROR,
(l_current_data + l_seg->newlen > p_src_data + p_max_length) ||
(partial_buffer)) {
opj_event_msg(p_manager, EVT_WARNING,
"read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
return OPJ_FALSE;
// skip this codeblock since it is a partial read
partial_buffer = 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
partial_buffer = 1;
partial_buffer = OPJ_TRUE;

l_cblk->numchunks = 0;

l_seg->numpasses += l_seg->numnewpasses;
l_cblk->numnewpasses -= l_seg->numnewpasses;
if (l_cblk->numnewpasses > 0) {
++l_seg;
++l_cblk->numsegs;
}
if(l_cblk->numnewpasses > 0) {
break;
}
continue;
}

#ifdef USE_JPWL
Expand Down Expand Up @@ -1456,8 +1476,12 @@ 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 the number of bytes read
if(partial_buffer) {
*(p_data_read) = p_max_length;
} else {
*(p_data_read) = (OPJ_UINT32)(l_current_data - p_src_data);
}

return OPJ_TRUE;
}
Expand Down Expand Up @@ -1523,7 +1547,7 @@ static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2,
"skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
return OPJ_FALSE;
//return OPJ_FALSE;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this commented line should be removed, and the message above turned as a EVT_WARNING ... when we allow decoding of partial bitstream.

I would like to see a public function
OPJ_API OPJ_BOOL OPJ_CALLCONV opj_decoder_set_strict_mode(opj_codec_t *p_codec, OPJ_BOOL strict)
to control if we allow or not partial bitstreams.
We could potentially change the default to be the relaxed mode implemented in that PR, but if the user want the previous behaviour, they would call opj_decoder_set_strict_mode(codec, OPJ_TRUE). In that case the warnings should be errors, and the return OPJ_FALSE that have been removed would be used.

}

#ifdef USE_JPWL
Expand Down