Skip to content

Commit 86522c8

Browse files
committed
Issue #15 is addressed in this commit. Segments TLM, PRF, PLM, PLT, CPF 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.
1 parent e94e85c commit 86522c8

File tree

8 files changed

+141
-47
lines changed

8 files changed

+141
-47
lines changed

src/apps/apps.xcodeproj/xcshareddata/xcschemes/ojph_expand.xcscheme

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,15 @@
6262
</BuildableProductRunnable>
6363
<CommandLineArguments>
6464
<CommandLineArgument
65-
argument = "-i test.j2c"
65+
argument = "-i test.jph"
6666
isEnabled = "YES">
6767
</CommandLineArgument>
6868
<CommandLineArgument
6969
argument = "-o test.yuv"
7070
isEnabled = "NO">
7171
</CommandLineArgument>
7272
<CommandLineArgument
73-
argument = "-o test_out.ppm"
73+
argument = "-o test.ppm"
7474
isEnabled = "YES">
7575
</CommandLineArgument>
7676
<CommandLineArgument

src/core/codestream/ojph_codestream.cpp

Lines changed: 109 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -463,13 +463,11 @@ namespace ojph {
463463
if (marker_idx == 0)
464464
cap.read(file);
465465
else if (marker_idx == 1)
466-
skip_marker(file, "PRF",
467-
"Skipping PRF marker segment; this should not cause any issues.",
468-
OJPH_MSG_LEVEL::NO_MSG);
466+
//Skipping PRF marker segment; this should not cause any issues
467+
skip_marker(file, "PRF", NULL, OJPH_MSG_LEVEL::NO_MSG);
469468
else if (marker_idx == 2)
470-
skip_marker(file, "CPF",
471-
"Skipping CPF marker segment; this should not cause any issues.",
472-
OJPH_MSG_LEVEL::NO_MSG);
469+
//Skipping CPF marker segment; this should not cause any issues
470+
skip_marker(file, "CPF", NULL, OJPH_MSG_LEVEL::NO_MSG);
473471
else if (marker_idx == 3)
474472
{ cod.read(file); received_markers |= 1; }
475473
else if (marker_idx == 4)
@@ -490,14 +488,19 @@ namespace ojph {
490488
skip_marker(file, "PPM", "PPM is not supported yet",
491489
OJPH_MSG_LEVEL::WARN);
492490
else if (marker_idx == 10)
493-
skip_marker(file, "TLM", "TLM is not supported yet",
494-
OJPH_MSG_LEVEL::WARN);
491+
//Skipping TLM marker segment; this should not cause any issues
492+
skip_marker(file, "TLM", NULL, OJPH_MSG_LEVEL::NO_MSG);
495493
else if (marker_idx == 11)
496-
skip_marker(file, "PLM", "PLM is not supported yet",
497-
OJPH_MSG_LEVEL::WARN);
494+
//Skipping PLM marker segment; this should not cause any issues
495+
skip_marker(file, "PLM", NULL, OJPH_MSG_LEVEL::NO_MSG);
498496
else if (marker_idx == 12)
499-
skip_marker(file, "CRG", "CRG is not supported yet",
500-
OJPH_MSG_LEVEL::WARN);
497+
//Skipping CRG marker segment;
498+
skip_marker(file, "CRG", "CRG has been ignored; CRG is related to"
499+
" where the Cb and Cr colour components are co-sited or located"
500+
" with respect to the Y' luma component. Perhaps, it is better"
501+
" to get the indivdual components and assemble the samples"
502+
" according to your needs",
503+
OJPH_MSG_LEVEL::INFO);
501504
else if (marker_idx == 13)
502505
skip_marker(file, "COM", NULL, OJPH_MSG_LEVEL::NO_MSG);
503506
else if (marker_idx == 14)
@@ -523,6 +526,7 @@ namespace ojph {
523526
{
524527
param_sot_t sot;
525528
sot.read(infile);
529+
ui64 tile_start_location = infile->tell();
526530

527531
if (sot.get_tile_index() > (int)num_tiles.area())
528532
OJPH_ERROR(0x00030061, "wrong tile index");
@@ -547,16 +551,17 @@ namespace ojph {
547551
skip_marker(infile, "PPT", "PPT in a tile is not supported yet",
548552
OJPH_MSG_LEVEL::WARN);
549553
else if (marker_idx == 2)
550-
skip_marker(infile, "PLT", "PLT in a tile is not supported yet",
551-
OJPH_MSG_LEVEL::WARN);
554+
//Skipping PLT marker segment; this should not cause any issues
555+
skip_marker(infile, "PLT", NULL, OJPH_MSG_LEVEL::NO_MSG);
552556
else if (marker_idx == 3)
553557
skip_marker(infile, "COM", NULL, OJPH_MSG_LEVEL::NO_MSG);
554558
else if (marker_idx == 4)
555559
break;
556560
else
557561
OJPH_ERROR(0x00030063, "unknown marker in a tile header");
558562
}
559-
tiles[sot.get_tile_index()].parse_tile_header(sot, infile);
563+
tiles[sot.get_tile_index()].parse_tile_header(sot, infile,
564+
tile_start_location);
560565
}
561566
else
562567
{ //first tile part
@@ -588,24 +593,25 @@ namespace ojph {
588593
skip_marker(infile, "PPT", "PPT in a tile is not supported yet",
589594
OJPH_MSG_LEVEL::WARN);
590595
else if (marker_idx == 7)
591-
skip_marker(infile, "PLT", "PLT in a tile is not supported yet",
592-
OJPH_MSG_LEVEL::WARN);
596+
//Skipping PLT marker segment; this should not cause any issues
597+
skip_marker(infile, "PLT", NULL, OJPH_MSG_LEVEL::NO_MSG);
593598
else if (marker_idx == 8)
594599
skip_marker(infile, "COM", NULL, OJPH_MSG_LEVEL::NO_MSG);
595600
else if (marker_idx == 9)
596601
break;
597602
else
598603
OJPH_ERROR(0x00030064, "unknown marker in a tile header");
599604
}
600-
tiles[sot.get_tile_index()].parse_tile_header(sot, infile);
605+
tiles[sot.get_tile_index()].parse_tile_header(sot, infile,
606+
tile_start_location);
601607
}
602608
// check the next marker; either SOT or EOC,
603609
// if something is broken, just an end of file
604610
ui16 next_markers[2] = { SOT, EOC };
605611
int marker_idx = find_marker(infile, next_markers, 2);
606612
if (marker_idx == -1)
607613
{
608-
OJPH_ERROR(0x00030065, "file termianted early");
614+
OJPH_INFO(0x00030021, "file terminated early");
609615
break;
610616
}
611617
else if (marker_idx == 0)
@@ -1147,16 +1153,26 @@ namespace ojph {
11471153
}
11481154

11491155
//////////////////////////////////////////////////////////////////////////
1150-
void tile::parse_tile_header(const param_sot_t &sot, infile_base *file)
1156+
void tile::parse_tile_header(const param_sot_t &sot, infile_base *file,
1157+
const ui64& tile_start_location)
11511158
{
1152-
if (this->sot.get_tile_part_index() != next_tile_part)
1159+
if (sot.get_tile_part_index() != next_tile_part)
11531160
OJPH_ERROR(0x00030091, "wrong tile part index");
11541161
this->sot.append(sot.get_length());
11551162
++next_tile_part;
11561163

1157-
long tile_end_location = file->tell() + sot.get_length();//used on
1158-
//failure
1164+
//tile_end_location used on failure
1165+
ui64 tile_end_location = tile_start_location + sot.get_length();
1166+
11591167
int data_left = sot.get_length(); //how many bytes left to parse
1168+
data_left -= file->tell() - tile_start_location;
1169+
data_left += 2; //2 is the size of SOD
1170+
1171+
if (data_left == 0)
1172+
return;
1173+
else if (data_left < 0)
1174+
OJPH_ERROR(0x00030092, "a tile part that has less than 0 bytes;"
1175+
"something is wrong");
11601176

11611177
int max_decompositions = 0;
11621178
for (int c = 0; c < num_comps; ++c)
@@ -1170,7 +1186,8 @@ namespace ojph {
11701186
{
11711187
for (int r = 0; r <= max_decompositions; ++r)
11721188
for (int c = 0; c < num_comps; ++c)
1173-
comps[c].parse_precincts(r, data_left, file);
1189+
if (data_left > 0)
1190+
comps[c].parse_precincts(r, data_left, file);
11741191
}
11751192
else if (prog_order == OJPH_PO_RPCL)
11761193
{
@@ -1189,7 +1206,7 @@ namespace ojph {
11891206
else if (cur.y == smallest.y && cur.x < smallest.x)
11901207
{ smallest = cur; comp_num = c; }
11911208
}
1192-
if (comp_num >= 0)
1209+
if (comp_num >= 0 && data_left > 0)
11931210
comps[comp_num].parse_one_precinct(r, data_left, file);
11941211
else
11951212
break;
@@ -1221,7 +1238,7 @@ namespace ojph {
12211238
{ smallest = cur; comp_num = c; res_num = r; }
12221239
}
12231240
}
1224-
if (comp_num >= 0)
1241+
if (comp_num >= 0 && data_left > 0)
12251242
comps[comp_num].parse_one_precinct(res_num, data_left, file);
12261243
else
12271244
break;
@@ -1244,7 +1261,7 @@ namespace ojph {
12441261
else if (cur.y == smallest.y && cur.x < smallest.x)
12451262
{ smallest = cur; res_num = r; }
12461263
}
1247-
if (res_num >= 0)
1264+
if (res_num >= 0 && data_left > 0)
12481265
comps[c].parse_one_precinct(res_num, data_left, file);
12491266
else
12501267
break;
@@ -1257,7 +1274,7 @@ namespace ojph {
12571274
}
12581275
catch (const char *error)
12591276
{
1260-
OJPH_WARN(0x00030011, "%s\n", error);
1277+
OJPH_INFO(0x00030011, "%s\n", error);
12611278
}
12621279
file->seek(tile_end_location, infile_base::OJPH_SEEK_SET);
12631280
}
@@ -1627,6 +1644,8 @@ namespace ojph {
16271644
pp->special_y = test_y && y == 0;
16281645
pp->num_bands = num_bands;
16291646
pp->bands = bands;
1647+
pp->may_use_sop = cd.packets_may_use_sop();
1648+
pp->uses_eph = cd.packets_use_eph();
16301649
}
16311650
}
16321651
if (num_bands == 1)
@@ -2130,7 +2149,7 @@ namespace ojph {
21302149
int idx = cur_precinct_loc.x + cur_precinct_loc.y * num_precincts.w;
21312150
for (size_t i = idx; i < num_precincts.area(); ++i)
21322151
{
2133-
if (data_left == 0)
2152+
if (data_left <= 0)
21342153
break;
21352154
p[i].parse(tag_tree_size, level_index, elastic, data_left, file);
21362155
if (++cur_precinct_loc.x >= num_precincts.w)
@@ -2147,7 +2166,7 @@ namespace ojph {
21472166
int idx = cur_precinct_loc.x + cur_precinct_loc.y * num_precincts.w;
21482167
assert(idx < (int)num_precincts.area());
21492168

2150-
if (data_left == 0)
2169+
if (data_left <= 0)
21512170
return;
21522171
precinct *p = precincts + idx;
21532172
p->parse(tag_tree_size, level_index, elastic, data_left, file);
@@ -2663,17 +2682,72 @@ namespace ojph {
26632682

26642683
//////////////////////////////////////////////////////////////////////////
26652684
static inline
2666-
bool terminate(bit_read_buf *bbp)
2685+
void bb_skip_eph(bit_read_buf *bbp)
2686+
{
2687+
if (bbp->bytes_left >= 2)
2688+
{
2689+
ui8 marker[2];
2690+
if (bbp->file->read(marker, 2) != 2)
2691+
throw "error reading from file";
2692+
bbp->bytes_left -= 2;
2693+
if ((int)marker[0] != (EPH >> 8) || (int)marker[1] != (EPH & 0xFF))
2694+
throw "should find EPH, but found something else";
2695+
}
2696+
}
2697+
2698+
//////////////////////////////////////////////////////////////////////////
2699+
static inline
2700+
bool bb_terminate(bit_read_buf *bbp, bool uses_eph)
26672701
{
26682702
bool result = true;
26692703
if (bbp->unstuff)
26702704
result = bb_read(bbp);
26712705
assert(bbp->unstuff == false);
2706+
if (uses_eph)
2707+
bb_skip_eph(bbp);
26722708
bbp->tmp = 0;
26732709
bbp->avail_bits = 0;
26742710
return result;
26752711
}
26762712

2713+
//////////////////////////////////////////////////////////////////////////
2714+
static inline
2715+
bool bb_skip_sop(bit_read_buf *bbp)
2716+
{
2717+
if (bbp->bytes_left >= 2)
2718+
{
2719+
ui8 marker[2];
2720+
if (bbp->file->read(marker, 2) != 2)
2721+
throw "error reading from file";
2722+
if ((int)marker[0] == (SOP >> 8) && (int)marker[1] == (SOP & 0xFF))
2723+
{
2724+
bbp->bytes_left -= 2;
2725+
if (bbp->bytes_left >= 4)
2726+
{
2727+
ui16 com_len;
2728+
if (bbp->file->read(&com_len, 2) != 2)
2729+
OJPH_ERROR(0x000300A1, "error reading from file");
2730+
com_len = swap_byte(com_len);
2731+
if (bbp->file->seek(com_len - 2, infile_base::OJPH_SEEK_CUR) != 0)
2732+
throw "error seeking file";
2733+
bbp->bytes_left -= com_len;
2734+
if (com_len != 4)
2735+
throw "something is wrong with SOP length";
2736+
}
2737+
return true;
2738+
}
2739+
else
2740+
{
2741+
//put the bytes back
2742+
if (bbp->file->seek(-2, infile_base::OJPH_SEEK_CUR) != 0)
2743+
throw "error seeking file";
2744+
return false;
2745+
}
2746+
}
2747+
2748+
return false;
2749+
}
2750+
26772751
//////////////////////////////////////////////////////////////////////////
26782752
void precinct::parse(int tag_tree_size, si32* lev_idx,
26792753
mem_elastic_allocator *elastic,
@@ -2682,6 +2756,8 @@ namespace ojph {
26822756
assert(data_left);
26832757
bit_read_buf bb;
26842758
bb_init(&bb, data_left, file);
2759+
if (may_use_sop)
2760+
bb_skip_sop(&bb);
26852761

26862762
int sst = num_bands == 3 ? 1 : 0;
26872763
int send = num_bands == 3 ? 4 : 1;
@@ -2696,7 +2772,7 @@ namespace ojph {
26962772
ui32 bit;
26972773
bb_read_bit(&bb, bit);
26982774
if (bit == 0) //empty packet
2699-
{ terminate(&bb); data_left = bb.bytes_left; return; }
2775+
{ bb_terminate(&bb, uses_eph); data_left = bb.bytes_left; return; }
27002776
empty_packet = false;
27012777
}
27022778

@@ -2830,7 +2906,7 @@ namespace ojph {
28302906
}
28312907
}
28322908
}
2833-
terminate(&bb);
2909+
bb_terminate(&bb, uses_eph);
28342910
//read codeblock data
28352911
for (int s = sst; s < send; ++s)
28362912
{

src/core/codestream/ojph_codestream_local.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ namespace ojph {
136136

137137
bool push(line_buf *line, int comp_num);
138138
void flush(outfile_base *file);
139-
void parse_tile_header(const param_sot_t& sot, infile_base *file);
139+
void parse_tile_header(const param_sot_t& sot, infile_base *file,
140+
const ui64& tile_start_location);
140141
bool pull(line_buf *, int comp_num);
141142

142143
private:
@@ -260,6 +261,7 @@ namespace ojph {
260261
coded_lists* coded;
261262
int num_bands;
262263
bool special_x, special_y;
264+
bool may_use_sop, uses_eph;
263265
};
264266

265267
//////////////////////////////////////////////////////////////////////////

src/core/codestream/ojph_params.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,19 @@ namespace ojph {
329329
return (state->SGCod.mc_trans == 0 ? false : true);
330330
}
331331

332+
////////////////////////////////////////////////////////////////////////////
333+
bool param_cod_t::packets_may_use_sop() const
334+
{
335+
return (state->Scod & 2) == 2;
336+
}
337+
338+
////////////////////////////////////////////////////////////////////////////
339+
bool param_cod_t::packets_use_eph() const
340+
{
341+
return (state->Scod & 4) == 4;
342+
}
343+
344+
332345
////////////////////////////////////////////////////////////////////////////
333346
//
334347
//

src/core/codestream/ojph_params_local.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,27 +78,26 @@ namespace ojph {
7878
CAP = 0xFF50, //extended capability
7979
SIZ = 0xFF51, //image and tile size (required)
8080
COD = 0xFF52, //coding style default (required)
81+
TLM = 0xFF55, //tile-part lengths
82+
PRF = 0xFF56, //profile
83+
PLM = 0xFF57, //packet length, main header
84+
PLT = 0xFF58, //packet length, tile-part header
85+
CPF = 0xFF59, //corresponding profile values
8186
QCD = 0xFF5C, //qunatization default (required)
8287
COM = 0xFF64, //comment
83-
EOC = 0xFFD9, //end of codestream (required)
8488
SOT = 0xFF90, //start of tile-part
89+
SOP = 0xFF91, //start of packet
90+
EPH = 0xFF92, //end of packet
8591
SOD = 0xFF93, //start of data
92+
EOC = 0xFFD9, //end of codestream (required)
8693

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

104103
//////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)