Skip to content

Commit

Permalink
Issue #15 is addressed in this commit. Segments TLM, PRF, PLM, PLT, C…
Browse files Browse the repository at this point in the history
…PF should not generate any error messages as they are skipped. SOP and EPH are consumed correctly and therefore no error messages are generated. Some of the error/warn messages have been downgraded to info. CRG is still skipped but gives an info messages suggesting extracting the individual components and assembling them as the end user desires. OpenJPH version has been pushed to 0.5.0.
  • Loading branch information
aous72 committed Jan 6, 2020
1 parent e94e85c commit 86522c8
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 47 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-i test.j2c"
argument = "-i test.jph"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
argument = "-o test.yuv"
isEnabled = "NO">
</CommandLineArgument>
<CommandLineArgument
argument = "-o test_out.ppm"
argument = "-o test.ppm"
isEnabled = "YES">
</CommandLineArgument>
<CommandLineArgument
Expand Down
142 changes: 109 additions & 33 deletions src/core/codestream/ojph_codestream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -463,13 +463,11 @@ namespace ojph {
if (marker_idx == 0)
cap.read(file);
else if (marker_idx == 1)
skip_marker(file, "PRF",
"Skipping PRF marker segment; this should not cause any issues.",
OJPH_MSG_LEVEL::NO_MSG);
//Skipping PRF marker segment; this should not cause any issues
skip_marker(file, "PRF", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 2)
skip_marker(file, "CPF",
"Skipping CPF marker segment; this should not cause any issues.",
OJPH_MSG_LEVEL::NO_MSG);
//Skipping CPF marker segment; this should not cause any issues
skip_marker(file, "CPF", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 3)
{ cod.read(file); received_markers |= 1; }
else if (marker_idx == 4)
Expand All @@ -490,14 +488,19 @@ namespace ojph {
skip_marker(file, "PPM", "PPM is not supported yet",
OJPH_MSG_LEVEL::WARN);
else if (marker_idx == 10)
skip_marker(file, "TLM", "TLM is not supported yet",
OJPH_MSG_LEVEL::WARN);
//Skipping TLM marker segment; this should not cause any issues
skip_marker(file, "TLM", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 11)
skip_marker(file, "PLM", "PLM is not supported yet",
OJPH_MSG_LEVEL::WARN);
//Skipping PLM marker segment; this should not cause any issues
skip_marker(file, "PLM", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 12)
skip_marker(file, "CRG", "CRG is not supported yet",
OJPH_MSG_LEVEL::WARN);
//Skipping CRG marker segment;
skip_marker(file, "CRG", "CRG has been ignored; CRG is related to"
" where the Cb and Cr colour components are co-sited or located"
" with respect to the Y' luma component. Perhaps, it is better"
" to get the indivdual components and assemble the samples"
" according to your needs",
OJPH_MSG_LEVEL::INFO);
else if (marker_idx == 13)
skip_marker(file, "COM", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 14)
Expand All @@ -523,6 +526,7 @@ namespace ojph {
{
param_sot_t sot;
sot.read(infile);
ui64 tile_start_location = infile->tell();

if (sot.get_tile_index() > (int)num_tiles.area())
OJPH_ERROR(0x00030061, "wrong tile index");
Expand All @@ -547,16 +551,17 @@ namespace ojph {
skip_marker(infile, "PPT", "PPT in a tile is not supported yet",
OJPH_MSG_LEVEL::WARN);
else if (marker_idx == 2)
skip_marker(infile, "PLT", "PLT in a tile is not supported yet",
OJPH_MSG_LEVEL::WARN);
//Skipping PLT marker segment; this should not cause any issues
skip_marker(infile, "PLT", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 3)
skip_marker(infile, "COM", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 4)
break;
else
OJPH_ERROR(0x00030063, "unknown marker in a tile header");
}
tiles[sot.get_tile_index()].parse_tile_header(sot, infile);
tiles[sot.get_tile_index()].parse_tile_header(sot, infile,
tile_start_location);
}
else
{ //first tile part
Expand Down Expand Up @@ -588,24 +593,25 @@ namespace ojph {
skip_marker(infile, "PPT", "PPT in a tile is not supported yet",
OJPH_MSG_LEVEL::WARN);
else if (marker_idx == 7)
skip_marker(infile, "PLT", "PLT in a tile is not supported yet",
OJPH_MSG_LEVEL::WARN);
//Skipping PLT marker segment; this should not cause any issues
skip_marker(infile, "PLT", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 8)
skip_marker(infile, "COM", NULL, OJPH_MSG_LEVEL::NO_MSG);
else if (marker_idx == 9)
break;
else
OJPH_ERROR(0x00030064, "unknown marker in a tile header");
}
tiles[sot.get_tile_index()].parse_tile_header(sot, infile);
tiles[sot.get_tile_index()].parse_tile_header(sot, infile,
tile_start_location);
}
// check the next marker; either SOT or EOC,
// if something is broken, just an end of file
ui16 next_markers[2] = { SOT, EOC };
int marker_idx = find_marker(infile, next_markers, 2);
if (marker_idx == -1)
{
OJPH_ERROR(0x00030065, "file termianted early");
OJPH_INFO(0x00030021, "file terminated early");
break;
}
else if (marker_idx == 0)
Expand Down Expand Up @@ -1147,16 +1153,26 @@ namespace ojph {
}

//////////////////////////////////////////////////////////////////////////
void tile::parse_tile_header(const param_sot_t &sot, infile_base *file)
void tile::parse_tile_header(const param_sot_t &sot, infile_base *file,
const ui64& tile_start_location)
{
if (this->sot.get_tile_part_index() != next_tile_part)
if (sot.get_tile_part_index() != next_tile_part)
OJPH_ERROR(0x00030091, "wrong tile part index");
this->sot.append(sot.get_length());
++next_tile_part;

long tile_end_location = file->tell() + sot.get_length();//used on
//failure
//tile_end_location used on failure
ui64 tile_end_location = tile_start_location + sot.get_length();

int data_left = sot.get_length(); //how many bytes left to parse
data_left -= file->tell() - tile_start_location;
data_left += 2; //2 is the size of SOD

if (data_left == 0)
return;
else if (data_left < 0)
OJPH_ERROR(0x00030092, "a tile part that has less than 0 bytes;"
"something is wrong");

int max_decompositions = 0;
for (int c = 0; c < num_comps; ++c)
Expand All @@ -1170,7 +1186,8 @@ namespace ojph {
{
for (int r = 0; r <= max_decompositions; ++r)
for (int c = 0; c < num_comps; ++c)
comps[c].parse_precincts(r, data_left, file);
if (data_left > 0)
comps[c].parse_precincts(r, data_left, file);
}
else if (prog_order == OJPH_PO_RPCL)
{
Expand All @@ -1189,7 +1206,7 @@ namespace ojph {
else if (cur.y == smallest.y && cur.x < smallest.x)
{ smallest = cur; comp_num = c; }
}
if (comp_num >= 0)
if (comp_num >= 0 && data_left > 0)
comps[comp_num].parse_one_precinct(r, data_left, file);
else
break;
Expand Down Expand Up @@ -1221,7 +1238,7 @@ namespace ojph {
{ smallest = cur; comp_num = c; res_num = r; }
}
}
if (comp_num >= 0)
if (comp_num >= 0 && data_left > 0)
comps[comp_num].parse_one_precinct(res_num, data_left, file);
else
break;
Expand All @@ -1244,7 +1261,7 @@ namespace ojph {
else if (cur.y == smallest.y && cur.x < smallest.x)
{ smallest = cur; res_num = r; }
}
if (res_num >= 0)
if (res_num >= 0 && data_left > 0)
comps[c].parse_one_precinct(res_num, data_left, file);
else
break;
Expand All @@ -1257,7 +1274,7 @@ namespace ojph {
}
catch (const char *error)
{
OJPH_WARN(0x00030011, "%s\n", error);
OJPH_INFO(0x00030011, "%s\n", error);
}
file->seek(tile_end_location, infile_base::OJPH_SEEK_SET);
}
Expand Down Expand Up @@ -1627,6 +1644,8 @@ namespace ojph {
pp->special_y = test_y && y == 0;
pp->num_bands = num_bands;
pp->bands = bands;
pp->may_use_sop = cd.packets_may_use_sop();
pp->uses_eph = cd.packets_use_eph();
}
}
if (num_bands == 1)
Expand Down Expand Up @@ -2130,7 +2149,7 @@ namespace ojph {
int idx = cur_precinct_loc.x + cur_precinct_loc.y * num_precincts.w;
for (size_t i = idx; i < num_precincts.area(); ++i)
{
if (data_left == 0)
if (data_left <= 0)
break;
p[i].parse(tag_tree_size, level_index, elastic, data_left, file);
if (++cur_precinct_loc.x >= num_precincts.w)
Expand All @@ -2147,7 +2166,7 @@ namespace ojph {
int idx = cur_precinct_loc.x + cur_precinct_loc.y * num_precincts.w;
assert(idx < (int)num_precincts.area());

if (data_left == 0)
if (data_left <= 0)
return;
precinct *p = precincts + idx;
p->parse(tag_tree_size, level_index, elastic, data_left, file);
Expand Down Expand Up @@ -2663,17 +2682,72 @@ namespace ojph {

//////////////////////////////////////////////////////////////////////////
static inline
bool terminate(bit_read_buf *bbp)
void bb_skip_eph(bit_read_buf *bbp)
{
if (bbp->bytes_left >= 2)
{
ui8 marker[2];
if (bbp->file->read(marker, 2) != 2)
throw "error reading from file";
bbp->bytes_left -= 2;
if ((int)marker[0] != (EPH >> 8) || (int)marker[1] != (EPH & 0xFF))
throw "should find EPH, but found something else";
}
}

//////////////////////////////////////////////////////////////////////////
static inline
bool bb_terminate(bit_read_buf *bbp, bool uses_eph)
{
bool result = true;
if (bbp->unstuff)
result = bb_read(bbp);
assert(bbp->unstuff == false);
if (uses_eph)
bb_skip_eph(bbp);
bbp->tmp = 0;
bbp->avail_bits = 0;
return result;
}

//////////////////////////////////////////////////////////////////////////
static inline
bool bb_skip_sop(bit_read_buf *bbp)
{
if (bbp->bytes_left >= 2)
{
ui8 marker[2];
if (bbp->file->read(marker, 2) != 2)
throw "error reading from file";
if ((int)marker[0] == (SOP >> 8) && (int)marker[1] == (SOP & 0xFF))
{
bbp->bytes_left -= 2;
if (bbp->bytes_left >= 4)
{
ui16 com_len;
if (bbp->file->read(&com_len, 2) != 2)
OJPH_ERROR(0x000300A1, "error reading from file");
com_len = swap_byte(com_len);
if (bbp->file->seek(com_len - 2, infile_base::OJPH_SEEK_CUR) != 0)
throw "error seeking file";
bbp->bytes_left -= com_len;
if (com_len != 4)
throw "something is wrong with SOP length";
}
return true;
}
else
{
//put the bytes back
if (bbp->file->seek(-2, infile_base::OJPH_SEEK_CUR) != 0)
throw "error seeking file";
return false;
}
}

return false;
}

//////////////////////////////////////////////////////////////////////////
void precinct::parse(int tag_tree_size, si32* lev_idx,
mem_elastic_allocator *elastic,
Expand All @@ -2682,6 +2756,8 @@ namespace ojph {
assert(data_left);
bit_read_buf bb;
bb_init(&bb, data_left, file);
if (may_use_sop)
bb_skip_sop(&bb);

int sst = num_bands == 3 ? 1 : 0;
int send = num_bands == 3 ? 4 : 1;
Expand All @@ -2696,7 +2772,7 @@ namespace ojph {
ui32 bit;
bb_read_bit(&bb, bit);
if (bit == 0) //empty packet
{ terminate(&bb); data_left = bb.bytes_left; return; }
{ bb_terminate(&bb, uses_eph); data_left = bb.bytes_left; return; }
empty_packet = false;
}

Expand Down Expand Up @@ -2830,7 +2906,7 @@ namespace ojph {
}
}
}
terminate(&bb);
bb_terminate(&bb, uses_eph);
//read codeblock data
for (int s = sst; s < send; ++s)
{
Expand Down
4 changes: 3 additions & 1 deletion src/core/codestream/ojph_codestream_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ namespace ojph {

bool push(line_buf *line, int comp_num);
void flush(outfile_base *file);
void parse_tile_header(const param_sot_t& sot, infile_base *file);
void parse_tile_header(const param_sot_t& sot, infile_base *file,
const ui64& tile_start_location);
bool pull(line_buf *, int comp_num);

private:
Expand Down Expand Up @@ -260,6 +261,7 @@ namespace ojph {
coded_lists* coded;
int num_bands;
bool special_x, special_y;
bool may_use_sop, uses_eph;
};

//////////////////////////////////////////////////////////////////////////
Expand Down
13 changes: 13 additions & 0 deletions src/core/codestream/ojph_params.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,19 @@ namespace ojph {
return (state->SGCod.mc_trans == 0 ? false : true);
}

////////////////////////////////////////////////////////////////////////////
bool param_cod_t::packets_may_use_sop() const
{
return (state->Scod & 2) == 2;
}

////////////////////////////////////////////////////////////////////////////
bool param_cod_t::packets_use_eph() const
{
return (state->Scod & 4) == 4;
}


////////////////////////////////////////////////////////////////////////////
//
//
Expand Down
17 changes: 8 additions & 9 deletions src/core/codestream/ojph_params_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,27 +78,26 @@ namespace ojph {
CAP = 0xFF50, //extended capability
SIZ = 0xFF51, //image and tile size (required)
COD = 0xFF52, //coding style default (required)
TLM = 0xFF55, //tile-part lengths
PRF = 0xFF56, //profile
PLM = 0xFF57, //packet length, main header
PLT = 0xFF58, //packet length, tile-part header
CPF = 0xFF59, //corresponding profile values
QCD = 0xFF5C, //qunatization default (required)
COM = 0xFF64, //comment
EOC = 0xFFD9, //end of codestream (required)
SOT = 0xFF90, //start of tile-part
SOP = 0xFF91, //start of packet
EPH = 0xFF92, //end of packet
SOD = 0xFF93, //start of data
EOC = 0xFFD9, //end of codestream (required)

//These headers are not used in the first iteration of the code
COC = 0xFF53, //coding style component
TLM = 0xFF55, //tile-part lengths
PRF = 0xFF56, //profile
PLM = 0xFF57, //packet length, main header
PLT = 0xFF58, //packet length, tile-part header
CPF = 0xFF59, //corresponding profile values
QCC = 0xFF5D, //quantization component
RGN = 0xFF5E, //region of interest
POC = 0xFF5F, //progression order change
PPM = 0xFF60, //packed packet headers, main header
PPT = 0xFF61, //packed packet headers, tile-part header
CRG = 0xFF63, //component registration
SOP = 0xFF91, //start of packet
EPH = 0xFF92, //end of packet
};

//////////////////////////////////////////////////////////////////////////
Expand Down
Loading

0 comments on commit 86522c8

Please sign in to comment.