Skip to content

Commit

Permalink
T1 decoder: check code stream errors when predictable termination is …
Browse files Browse the repository at this point in the history
…enabled and emit a warning when errors are found
  • Loading branch information
rouault committed Jul 20, 2016
1 parent 69497d3 commit c9f3d88
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/lib/openjp2/mqc.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ void opj_mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp) {
mqc->bp = bp - 1;
mqc->ct = 12;
mqc->start = bp;
mqc->end_of_byte_stream_counter = 0;
}

void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d) {
Expand Down Expand Up @@ -430,6 +431,7 @@ void opj_mqc_segmark_enc(opj_mqc_t *mqc) {

OPJ_BOOL opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len) {
opj_mqc_setcurctx(mqc, 0);
mqc->end_of_byte_stream_counter = 0;
mqc->start = bp;
mqc->end = bp + len;
mqc->bp = bp;
Expand Down
1 change: 1 addition & 0 deletions src/lib/openjp2/mqc.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ typedef struct opj_mqc {
OPJ_UINT32 c;
OPJ_UINT32 a;
OPJ_UINT32 ct;
OPJ_UINT32 end_of_byte_stream_counter; /* only used by decoder */
OPJ_BYTE *bp;
OPJ_BYTE *start;
OPJ_BYTE *end;
Expand Down
2 changes: 2 additions & 0 deletions src/lib/openjp2/mqc_inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc) {
if (c > 0x8f) {
mqc->c += 0xff00;
mqc->ct = 8;
mqc->end_of_byte_stream_counter ++;
} else {
mqc->bp++;
mqc->c += c << 9;
Expand All @@ -111,6 +112,7 @@ static INLINE void opj_mqc_bytein(opj_mqc_t *const mqc) {
mqc->ct = 8;
}
} else {
mqc->end_of_byte_stream_counter ++;
mqc->c += 0xff00;
mqc->ct = 8;
}
Expand Down
53 changes: 49 additions & 4 deletions src/lib/openjp2/t1.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,10 @@ static OPJ_BOOL opj_t1_decode_cblk( opj_t1_t *t1,
opj_tcd_cblk_dec_t* cblk,
OPJ_UINT32 orient,
OPJ_UINT32 roishift,
OPJ_UINT32 cblksty);
OPJ_UINT32 cblksty,
opj_event_mgr_t *p_manager,
opj_mutex_t* p_manager_mutex,
OPJ_BOOL check_pterm );

static OPJ_BOOL opj_t1_allocate_buffers( opj_t1_t *t1,
OPJ_UINT32 w,
Expand Down Expand Up @@ -1548,6 +1551,9 @@ typedef struct
opj_tcd_tilecomp_t* tilec;
opj_tccp_t* tccp;
volatile OPJ_BOOL* pret;
opj_event_mgr_t *p_manager;
opj_mutex_t* p_manager_mutex;
OPJ_BOOL check_pterm;
} opj_t1_cblk_decode_processing_job_t;

static void opj_t1_destroy_wrapper(void* t1)
Expand Down Expand Up @@ -1596,7 +1602,10 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls)
cblk,
band->bandno,
(OPJ_UINT32)tccp->roishift,
tccp->cblksty)) {
tccp->cblksty,
job->p_manager,
job->p_manager_mutex,
job->check_pterm )) {
*(job->pret) = OPJ_FALSE;
opj_free(job);
return;
Expand Down Expand Up @@ -1670,7 +1679,10 @@ static void opj_t1_clbl_decode_processor(void* user_data, opj_tls_t* tls)
void opj_t1_decode_cblks( opj_thread_pool_t* tp,
volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp
opj_tccp_t* tccp,
opj_event_mgr_t *p_manager,
opj_mutex_t* p_manager_mutex,
OPJ_BOOL check_pterm
)
{
OPJ_UINT32 resno, bandno, precno, cblkno;
Expand All @@ -1695,6 +1707,9 @@ void opj_t1_decode_cblks( opj_thread_pool_t* tp,
job->tilec = tilec;
job->tccp = tccp;
job->pret = pret;
job->p_manager_mutex = p_manager_mutex;
job->p_manager = p_manager;
job->check_pterm = check_pterm;
opj_thread_pool_submit_job( tp, opj_t1_clbl_decode_processor, job );
if( !(*pret) )
return;
Expand All @@ -1711,7 +1726,10 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
opj_tcd_cblk_dec_t* cblk,
OPJ_UINT32 orient,
OPJ_UINT32 roishift,
OPJ_UINT32 cblksty)
OPJ_UINT32 cblksty,
opj_event_mgr_t *p_manager,
opj_mutex_t* p_manager_mutex,
OPJ_BOOL check_pterm )
{
opj_raw_t *raw = t1->raw; /* RAW component */
opj_mqc_t *mqc = t1->mqc; /* MQC component */
Expand Down Expand Up @@ -1843,6 +1861,33 @@ static OPJ_BOOL opj_t1_decode_cblk(opj_t1_t *t1,
}
}
}

if (check_pterm)
{
if( mqc->bp+2 < mqc->end )
{
if( p_manager_mutex )
opj_mutex_lock( p_manager_mutex );
opj_event_msg(p_manager, EVT_WARNING,
"PTERM check failure: %d remaining bytes in code block (%d used / %d)\n",
(int)(mqc->end - mqc->bp) - 2,
(int)(mqc->bp - mqc->start),
(int)(mqc->end - mqc->start));
if( p_manager_mutex )
opj_mutex_unlock( p_manager_mutex );
}
else if( mqc->end_of_byte_stream_counter > 2)
{
if( p_manager_mutex )
opj_mutex_lock( p_manager_mutex );
opj_event_msg(p_manager, EVT_WARNING,
"PTERM check failure: %d synthetized 0xFF markers read\n",
mqc->end_of_byte_stream_counter);
if( p_manager_mutex )
opj_mutex_unlock( p_manager_mutex );
}
}

return OPJ_TRUE;
}

Expand Down
5 changes: 4 additions & 1 deletion src/lib/openjp2/t1.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,10 @@ Decode the code-blocks of a tile
void opj_t1_decode_cblks( opj_thread_pool_t* tp,
volatile OPJ_BOOL* pret,
opj_tcd_tilecomp_t* tilec,
opj_tccp_t* tccp);
opj_tccp_t* tccp,
opj_event_mgr_t *p_manager,
opj_mutex_t* p_manager_mutex,
OPJ_BOOL check_pterm);



Expand Down
24 changes: 20 additions & 4 deletions src/lib/openjp2/tcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ static OPJ_BOOL opj_tcd_t2_decode ( opj_tcd_t *p_tcd,
opj_codestream_index_t *p_cstr_index,
opj_event_mgr_t *p_manager);

static OPJ_BOOL opj_tcd_t1_decode (opj_tcd_t *p_tcd);
static OPJ_BOOL opj_tcd_t1_decode (opj_tcd_t *p_tcd,
opj_event_mgr_t *p_manager);

static OPJ_BOOL opj_tcd_dwt_decode (opj_tcd_t *p_tcd);

Expand Down Expand Up @@ -1295,7 +1296,7 @@ OPJ_BOOL opj_tcd_decode_tile( opj_tcd_t *p_tcd,

/* FIXME _ProfStart(PGROUP_T1); */
if
(! opj_tcd_t1_decode(p_tcd))
(! opj_tcd_t1_decode(p_tcd, p_manager))
{
return OPJ_FALSE;
}
Expand Down Expand Up @@ -1565,23 +1566,38 @@ static OPJ_BOOL opj_tcd_t2_decode (opj_tcd_t *p_tcd,
return OPJ_TRUE;
}

static OPJ_BOOL opj_tcd_t1_decode ( opj_tcd_t *p_tcd )
static OPJ_BOOL opj_tcd_t1_decode ( opj_tcd_t *p_tcd, opj_event_mgr_t *p_manager )
{
OPJ_UINT32 compno;
opj_tcd_tile_t * l_tile = p_tcd->tcd_image->tiles;
opj_tcd_tilecomp_t* l_tile_comp = l_tile->comps;
opj_tccp_t * l_tccp = p_tcd->tcp->tccps;
volatile OPJ_BOOL ret = OPJ_TRUE;
OPJ_BOOL check_pterm = OPJ_FALSE;
opj_mutex_t* p_manager_mutex = NULL;

p_manager_mutex = opj_mutex_create();

/* Only enable PTERM check if we decode all layers */
if( p_tcd->tcp->num_layers_to_decode == p_tcd->tcp->numlayers &&
(l_tccp->cblksty & J2K_CCP_CBLKSTY_PTERM) != 0 )
{
check_pterm = OPJ_TRUE;
}

for (compno = 0; compno < l_tile->numcomps; ++compno) {
opj_t1_decode_cblks(p_tcd->thread_pool, &ret, l_tile_comp, l_tccp);

opj_t1_decode_cblks(p_tcd->thread_pool, &ret, l_tile_comp, l_tccp,
p_manager, p_manager_mutex, check_pterm);
if( !ret )
break;
++l_tile_comp;
++l_tccp;
}

opj_thread_pool_wait_completion(p_tcd->thread_pool, 0);
if( p_manager_mutex )
opj_mutex_destroy( p_manager_mutex );

return ret;
}
Expand Down

0 comments on commit c9f3d88

Please sign in to comment.