diff options
| author | Antonin Descampe <antonin@gmail.com> | 2011-11-01 23:28:07 +0000 |
|---|---|---|
| committer | Antonin Descampe <antonin@gmail.com> | 2011-11-01 23:28:07 +0000 |
| commit | 49a0f0db8fe8c85f3e808e4857ee48322c47dcea (patch) | |
| tree | 2c2930cbf2e430fc65b444799888fb44a4742981 | |
| parent | 6a1530e4b1f6a607ed07cf9814d38e3759045f55 (diff) | |
[1.5] backport revisions 996, 997, 1000, 1008-1012 from trunk (JPIP modifications)
28 files changed, 1384 insertions, 872 deletions
@@ -7,6 +7,7 @@ What's New for OpenJPEG October 21, 2011 * [mickael] remove one obvious memory leak from test functions +! [kaori] change -v option was renamed to -u, which is equivalent to -TP long option October 20, 2011 * [mickael] remove obvious memory leak from applications diff --git a/applications/JavaOpenJPEG/JavaOpenJPEG.c b/applications/JavaOpenJPEG/JavaOpenJPEG.c index 0926b77c..eea41c25 100644 --- a/applications/JavaOpenJPEG/JavaOpenJPEG.c +++ b/applications/JavaOpenJPEG/JavaOpenJPEG.c @@ -204,6 +204,8 @@ void encode_help_display() { fprintf(stdout," Indicate multiple modes by adding their values. \n");
fprintf(stdout," ex: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n");
fprintf(stdout,"\n");
+ fprintf(stdout,"-TP : devide packets of every tile into tile-parts (-TP R) [R, L, C]\n");
+ fprintf(stdout,"\n");
fprintf(stdout,"-x : create an index file *.Idx (-x index_name.Idx) \n");
fprintf(stdout,"\n");
fprintf(stdout,"-ROI : c=%%d,U=%%d : quantization indices upshifted \n");
@@ -499,7 +501,7 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters, {"cinema2K",REQ_ARG, NULL ,'w'},
{"cinema4K",NO_ARG, NULL ,'y'},
{"ImgDir",REQ_ARG, NULL ,'z'},
- {"TP",REQ_ARG, NULL ,'v'},
+ {"TP",REQ_ARG, NULL ,'u'},
{"SOP",NO_ARG, NULL ,'S'},
{"EPH",NO_ARG, NULL ,'E'},
{"OutFor",REQ_ARG, NULL ,'O'},
@@ -510,7 +512,7 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters, /* parse the command line */
/* UniPG>> */
- const char optlist[] = "i:o:hr:q:n:b:c:t:p:s:SEM:x:R:d:T:If:P:C:F:"
+ const char optlist[] = "i:o:hr:q:n:b:c:t:p:s:SEM:x:R:d:T:If:P:C:F:u:J"
#ifdef USE_JPWL
"W:"
#endif /* USE_JPWL */
@@ -871,7 +873,7 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters, /* ------------------------------------------------------ */
- case 'v': /* Tile part generation*/
+ case 'u': /* Tile part generation*/
{
parameters->tp_flag = opj_optarg[0];
parameters->tp_on = 1;
diff --git a/applications/codec/image_to_j2k.c b/applications/codec/image_to_j2k.c index 93d0c6ff..968afcc6 100644 --- a/applications/codec/image_to_j2k.c +++ b/applications/codec/image_to_j2k.c @@ -193,6 +193,8 @@ void encode_help_display(void) { fprintf(stdout," Indicate multiple modes by adding their values. \n"); fprintf(stdout," ex: RESTART(4) + RESET(2) + SEGMARK(32) = -M 38\n"); fprintf(stdout,"\n"); + fprintf(stdout,"-TP : devide packets of every tile into tile-parts (-TP R) [R, L, C]\n"); + fprintf(stdout,"\n"); fprintf(stdout,"-x : create an index file *.Idx (-x index_name.Idx) \n"); fprintf(stdout,"\n"); fprintf(stdout,"-ROI : c=%%d,U=%%d : quantization indices upshifted \n"); @@ -581,7 +583,7 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters, {"cinema2K",REQ_ARG, NULL ,'w'}, {"cinema4K",NO_ARG, NULL ,'y'}, {"ImgDir",REQ_ARG, NULL ,'z'}, - {"TP",REQ_ARG, NULL ,'v'}, + {"TP",REQ_ARG, NULL ,'u'}, {"SOP",NO_ARG, NULL ,'S'}, {"EPH",NO_ARG, NULL ,'E'}, {"OutFor",REQ_ARG, NULL ,'O'}, @@ -591,7 +593,7 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters, }; /* parse the command line */ - const char optlist[] = "i:o:r:q:n:b:c:t:p:s:SEM:x:R:d:T:If:P:C:F:v:" + const char optlist[] = "i:o:r:q:n:b:c:t:p:s:SEM:x:R:d:T:If:P:C:F:u:J" #ifdef USE_JPWL "W:" #endif /* USE_JPWL */ @@ -1005,7 +1007,7 @@ int parse_cmdline_encoder(int argc, char **argv, opj_cparameters_t *parameters, /* ------------------------------------------------------ */ - case 'v': /* Tile part generation*/ + case 'u': /* Tile part generation*/ { parameters->tp_flag = opj_optarg[0]; parameters->tp_on = 1; diff --git a/applications/jpip/CHANGES b/applications/jpip/CHANGES index 34fa3cfc..c5ae11ad 100644 --- a/applications/jpip/CHANGES +++ b/applications/jpip/CHANGES @@ -5,6 +5,15 @@ What's New for OpenJPIP ! : changed + : added +October 14, 2011 +! [kaori] rearranged opj_server, opj_dec_server directory + +October 14, 2011 ++ [kaori] enable all progression orders + +October 12, 2011 ++ [kaori] enable layers requests; restricting the number of codesream quality layers + October 11, 2011 + [antonin] enable JPT-stream request from client viewer option (credit to kaori) diff --git a/applications/jpip/README b/applications/jpip/README index 0bd22fda..9842b936 100644 --- a/applications/jpip/README +++ b/applications/jpip/README @@ -126,11 +126,11 @@ Client: ---------- An example to encode a TIF image "copenhague1.tif" at resolution 4780x4050, 8bit/pixel, grayscale. - % ./image_to_j2k -i copenhague1.tif -o copenhague1.jp2 -p RPCL -c [64,64] -t 640,480 -jpip -v R + % ./image_to_j2k -i copenhague1.tif -o copenhague1.jp2 -p RPCL -c [64,64] -t 640,480 -jpip -TP R options -jpip : embed index table box into the output JP2 file (obligation for JPIP) - -v R : partition a tile into tile parts of different resolution levels (obligation for JPT-stream) + -TP R : partition a tile into tile parts of different resolution levels (obligation for JPT-stream) <Option> 3. Embed metadata into JP2 file diff --git a/applications/jpip/libopenjpip/j2kheader_manager.c b/applications/jpip/libopenjpip/j2kheader_manager.c index ad94d587..afbb2525 100644 --- a/applications/jpip/libopenjpip/j2kheader_manager.c +++ b/applications/jpip/libopenjpip/j2kheader_manager.c @@ -162,8 +162,7 @@ bool modify_mainheader( Byte_t *j2kstream, int numOfdecomp, SIZmarker_param_t SI if( !(newLcod = modify_CODmkrstream( COD, numOfdecomp, j2kstream))) return false; - // memmove( j2kstream+2+newLcod, j2kstream+2+COD.Lcod, (*j2klen)-(SIZ.Lsiz+newLcod+6));// new->oldLcod - memmove( j2kstream+2+newLcod, j2kstream+2+COD.Lcod, (*j2klen)-(SIZ.Lsiz+COD.Lcod+6)); + memmove( j2kstream+2+newLcod, j2kstream+2+COD.Lcod, (*j2klen)-(SIZ.Lsiz+COD.Lcod+6)); *j2klen -= ( COD.Lcod - newLcod); return true; @@ -222,6 +221,7 @@ Byte2_t modify_CODmkrstream( CODmarker_param_t COD, int numOfdecomp, Byte_t *COD newLcod = COD.Lcod; CODstream += 2; } + CODstream += 5; // skip Scod & SGcod // SPcod diff --git a/applications/jpip/libopenjpip/jp2k_encoder.c b/applications/jpip/libopenjpip/jp2k_encoder.c index e1488cde..5025bf8e 100644 --- a/applications/jpip/libopenjpip/jp2k_encoder.c +++ b/applications/jpip/libopenjpip/jp2k_encoder.c @@ -221,10 +221,11 @@ Byte_t * recons_codestream_from_JPTstream( msgqueue_param_t *msgqueue, Byte_t *j return j2kstream; } -Byte_t * recons_RPCLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, - Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, - int *max_reslev, Byte8_t *j2klen); +Byte_t * add_SOTmkr( Byte_t *j2kstream, Byte8_t *j2klen); +Byte_t * recons_bitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen); Byte_t * recons_codestream_from_JPPstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen) { @@ -244,11 +245,6 @@ Byte_t * recons_codestream_from_JPPstream( msgqueue_param_t *msgqueue, Byte_t *j if( !get_mainheader_from_j2kstream( j2kstream, &SIZ, &COD)) return j2kstream; - if( COD.prog_order != RPCL){ - fprintf( FCGI_stderr, "Error, Only RPCL order supported\n"); - return j2kstream; - } - if( fw == 0 || fh == 0) mindeclev = 0; else @@ -265,6 +261,7 @@ Byte_t * recons_codestream_from_JPPstream( msgqueue_param_t *msgqueue, Byte_t *j SOToffset = *j2klen; while(( ptr = search_message( TILE_HEADER_MSG, tileID, csn, ptr))!=NULL){ if( ptr->bin_offset == binOffset){ + j2kstream = add_SOTmkr( j2kstream, j2klen); j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen); foundTH = true; binOffset += ptr->length; @@ -273,17 +270,17 @@ Byte_t * recons_codestream_from_JPPstream( msgqueue_param_t *msgqueue, Byte_t *j } if( foundTH){ - j2kstream = recons_RPCLbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, &max_reslev, j2klen); + j2kstream = recons_bitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, &max_reslev, j2klen); modify_tileheader( j2kstream, SOToffset, (max_reslev<COD.numOfdecomp ? max_reslev : -1), SIZ.Csiz, j2klen); } else j2kstream = add_emptytilestream( tileID, j2kstream, j2klen); } - + if( max_reslev < COD.numOfdecomp) if( !modify_mainheader( j2kstream, max_reslev, SIZ, COD, j2klen)) return j2kstream; - + j2kstream = add_EOC( j2kstream, j2klen); return j2kstream; } @@ -306,55 +303,300 @@ Byte_t * add_mainhead_msgstream( msgqueue_param_t *msgqueue, Byte_t *origstream, return j2kstream; } -Byte_t * add_padding( Byte8_t padding, Byte_t *j2kstream, Byte8_t *j2klen); +Byte_t * add_SOTmkr( Byte_t *j2kstream, Byte8_t *j2klen) +{ + Byte_t *buf; + const Byte2_t SOT = 0x90ff; + + buf = (Byte_t *)malloc(( *j2klen)+2); + + memcpy( buf, j2kstream, *j2klen); + memcpy( buf+(*j2klen), &SOT, 2); + + *j2klen += 2; + + if(j2kstream) free(j2kstream); + + return buf; +} + +Byte_t * recons_LRCPbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen); + +Byte_t * recons_RLCPbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen); + +Byte_t * recons_RPCLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen); + +Byte_t * recons_PCRLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen); + +Byte_t * recons_CPRLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen); + +Byte_t * recons_bitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen) +{ + switch( COD.prog_order){ + case LRCP: + return recons_LRCPbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen); + case RLCP: + return recons_RLCPbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen); + case RPCL: + return recons_RPCLbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen); + case PCRL: + return recons_PCRLbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen); + case CPRL: + return recons_CPRLbitstream( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, mindeclev, max_reslev, j2klen); + default: + fprintf( FCGI_stderr, "Error, progression order not supported\n"); + } + return j2kstream; +} + +int comp_numOfprcts( Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int r); +Byte8_t comp_seqID( Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int r, int p); + +Byte_t * recons_packet( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int *max_reslev, + int comp_idx, int res_idx, int prct_idx, int lay_idx, Byte8_t *j2klen); + +Byte_t * recons_LRCPbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen) +{ + int r, p, c, l, numOfprcts; + + for( l=0; l<COD.numOflayers; l++) + for( r=0; r<=(COD.numOfdecomp-mindeclev); r++){ + if( COD.Scod & 0x01) + numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r); + else + numOfprcts = 1; + + for( c=0; c<SIZ.Csiz; c++) + for( p=0; p<numOfprcts; p++) + j2kstream = recons_packet( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, p, l, j2klen); + } + + return j2kstream; +} + +Byte_t * recons_RLCPbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen) +{ + int r, p, c, l, numOfprcts; + + for( r=0; r<=(COD.numOfdecomp-mindeclev); r++){ + if( COD.Scod & 0x01) + numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r); + else + numOfprcts = 1; + + for( l=0; l<COD.numOflayers; l++) + for( c=0; c<SIZ.Csiz; c++) + for( p=0; p<numOfprcts; p++) + j2kstream = recons_packet( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, p, l, j2klen); + } + + return j2kstream; +} + +Byte_t * recons_precinct( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int *max_reslev, + int comp_idx, int res_idx, Byte8_t seqID, Byte8_t *j2klen); Byte_t * recons_RPCLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, int *max_reslev, Byte8_t *j2klen) { int r, p, c, numOfprcts; - bool foundPrec; - Byte8_t binOffset, precID, seqID; - Byte4_t XTsiz, YTsiz; - message_param_t *ptr; + Byte8_t seqID; for( r=0, seqID=0; r<=(COD.numOfdecomp-mindeclev); r++){ - if( COD.Scod & 0x01){ - XTsiz = get_tile_XSiz( SIZ, tileID, COD.numOfdecomp-r); - YTsiz = get_tile_YSiz( SIZ, tileID, COD.numOfdecomp-r); - numOfprcts = ceil((double)XTsiz/(double)COD.XPsiz[r])*ceil((double)YTsiz/(double)COD.YPsiz[r]); - } + if( COD.Scod & 0x01) + numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r); else numOfprcts = 1; - for( p=0; p<numOfprcts; p++, seqID++){ - for( c=0; c<SIZ.Csiz; c++){ - - precID = comp_precinct_id( tileID, c, seqID, SIZ.Csiz, SIZ.XTnum*SIZ.YTnum); - - ptr = msgqueue->first; - binOffset = 0; - foundPrec = false; - while(( ptr = search_message( PRECINCT_MSG, precID, csn, ptr))!=NULL){ - if( ptr->bin_offset == binOffset){ - j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen); - - foundPrec = true; - binOffset += ptr->length; - if( *max_reslev < r) - *max_reslev = r; - } - ptr = ptr->next; - } - if(!foundPrec && COD.Scod & 0x01) - j2kstream = add_padding( 1, j2kstream, j2klen); + for( p=0; p<numOfprcts; p++, seqID++) + for( c=0; c<SIZ.Csiz; c++) + j2kstream = recons_precinct( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, seqID, j2klen); + } + + return j2kstream; +} + +Byte_t * recons_PCRLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen) +{ + int r, p, c, min_numOfprcts, numOfprcts, min_numOfres; + Byte8_t seqID; + + min_numOfres = COD.numOfdecomp-mindeclev + 1; + + if( COD.Scod & 0x01){ + min_numOfprcts = 0; + for( r=0; r<min_numOfres; r++){ + numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r); + + if( numOfprcts < min_numOfprcts || min_numOfprcts == 0) + min_numOfprcts = numOfprcts; + } + } + else + min_numOfprcts = 1; + + for( p=0; p<min_numOfprcts; p++) + for( c=0; c<SIZ.Csiz; c++) + for( r=0; r<min_numOfres; r++){ + seqID = comp_seqID( tileID, SIZ, COD, r, p); + j2kstream = recons_precinct( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, seqID, j2klen); + } + + return j2kstream; +} + + +Byte_t * recons_CPRLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int mindeclev, + int *max_reslev, Byte8_t *j2klen) +{ + int r, p, c, min_numOfprcts, numOfprcts, min_numOfres; + Byte8_t seqID; + + min_numOfres = COD.numOfdecomp-mindeclev + 1; + + if( COD.Scod & 0x01){ + min_numOfprcts = 0; + for( r=0; r<min_numOfres; r++){ + numOfprcts = comp_numOfprcts( tileID, SIZ, COD, r); + + if( numOfprcts < min_numOfprcts || min_numOfprcts == 0) + min_numOfprcts = numOfprcts; + } + } + else + min_numOfprcts = 1; + + for( c=0; c<SIZ.Csiz; c++) + for( p=0; p<min_numOfprcts; p++) + for( r=0; r<min_numOfres; r++){ + seqID = comp_seqID( tileID, SIZ, COD, r, p); + j2kstream = recons_precinct( msgqueue, jpipstream, j2kstream, csn, tileID, SIZ, COD, max_reslev, c, r, seqID, j2klen); + } + + return j2kstream; +} + +int comp_numOfprcts( Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int r) +{ + Byte4_t XTsiz, YTsiz; + + XTsiz = get_tile_XSiz( SIZ, tileID, COD.numOfdecomp-r); + YTsiz = get_tile_YSiz( SIZ, tileID, COD.numOfdecomp-r); + + return ceil((double)XTsiz/(double)COD.XPsiz[r])*ceil((double)YTsiz/(double)COD.YPsiz[r]); +} + +Byte_t * add_padding( Byte8_t padding, Byte_t *j2kstream, Byte8_t *j2klen); + +Byte_t * recons_packet( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int *max_reslev, + int comp_idx, int res_idx, int prct_idx, int lay_idx, Byte8_t *j2klen) +{ + Byte8_t seqID, precID, binOffset; + message_param_t *ptr; + bool foundPrec; + int l; + + seqID = comp_seqID( tileID, SIZ, COD, res_idx, prct_idx); + precID = comp_precinct_id( tileID, comp_idx, seqID, SIZ.Csiz, SIZ.XTnum*SIZ.YTnum); + + ptr = msgqueue->first; + binOffset = 0; + foundPrec = false; + l = 0; + + while(( ptr = search_message( PRECINCT_MSG, precID, csn, ptr))!=NULL){ + if( ptr->bin_offset == binOffset){ + if( lay_idx == l){ + j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen); + foundPrec = true; + if( *max_reslev < res_idx) + *max_reslev = res_idx; + + break; } + binOffset += ptr->length; + l++; } + ptr = ptr->next; } + if( !foundPrec && COD.Scod & 0x01) + j2kstream = add_padding( 1, j2kstream, j2klen); + return j2kstream; } + +Byte_t * recons_precinct( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, + Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int *max_reslev, + int comp_idx, int res_idx, Byte8_t seqID, Byte8_t *j2klen) +{ + Byte8_t precID, binOffset; + message_param_t *ptr; + bool foundPrec; + + precID = comp_precinct_id( tileID, comp_idx, seqID, SIZ.Csiz, SIZ.XTnum*SIZ.YTnum); + + ptr = msgqueue->first; + binOffset = 0; + foundPrec = false; + + while(( ptr = search_message( PRECINCT_MSG, precID, csn, ptr))!=NULL){ + if( ptr->bin_offset == binOffset){ + j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen); + + foundPrec = true; + binOffset += ptr->length; + if( *max_reslev < res_idx) + *max_reslev = res_idx; + + if( ptr->last_byte) + break; + } + ptr = ptr->next; + } + if(!foundPrec && COD.Scod & 0x01) + j2kstream = add_padding( COD.numOflayers, j2kstream, j2klen); + + return j2kstream; +} + +Byte8_t comp_seqID( Byte8_t tileID, SIZmarker_param_t SIZ, CODmarker_param_t COD, int r, int p) +{ + Byte8_t seqID = 0; + int rr; + + for( rr=0; rr<r; rr++) + seqID += comp_numOfprcts( tileID, SIZ, COD, rr); + + seqID += p; + + return seqID; +} + Byte8_t get_last_tileID( msgqueue_param_t *msgqueue, Byte8_t csn, bool isJPPstream) { Byte8_t last_tileID = 0; diff --git a/applications/jpip/libopenjpip/msgqueue_manager.c b/applications/jpip/libopenjpip/msgqueue_manager.c index 8cc89f48..295c2360 100644 --- a/applications/jpip/libopenjpip/msgqueue_manager.c +++ b/applications/jpip/libopenjpip/msgqueue_manager.c @@ -101,7 +101,8 @@ void print_msgqueue( msgqueue_param_t *msgqueue) fprintf( logstream, "\t csn: %lld\n", ptr->csn ); fprintf( logstream, "\t bin_offset: %#llx\n", ptr->bin_offset ); fprintf( logstream, "\t length: %#llx\n", ptr->length ); - fprintf( logstream, "\t aux: %lld\n", ptr->aux ); + if( ptr->class_id%2) + fprintf( logstream, "\t aux: %lld\n", ptr->aux ); fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte ); if( ptr->phld) print_placeholder( ptr->phld); @@ -162,9 +163,9 @@ void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue) msg->class_id = TILE_HEADER_MSG; msg->csn = target->csn; msg->bin_offset = 0; - msg->length = codeidx->tileheader[tile_id]->tlen; + msg->length = codeidx->tileheader[tile_id]->tlen-2; // SOT marker segment is removed msg->aux = 0; // non exist - msg->res_offset = codeidx->offset + get_elemOff( codeidx->tilepart, 0, tile_id); + msg->res_offset = codeidx->offset + get_elemOff( codeidx->tilepart, 0, tile_id) + 2; // skip SOT marker seg msg->phld = NULL; msg->next = NULL; @@ -210,7 +211,7 @@ void enqueue_tile( int tile_id, int level, msgqueue_param_t *msgqueue) if( !tp_model[i]){ msg = (message_param_t *)malloc( sizeof(message_param_t)); - msg->last_byte = i==numOftparts-1? true : false; + msg->last_byte = (i==numOftparts-1); msg->in_class_id = tile_id; msg->class_id = class_id; msg->csn = target->csn; @@ -229,35 +230,48 @@ void enqueue_tile( int tile_id, int level, msgqueue_param_t *msgqueue) } } -void enqueue_precinct( int seq_id, int tile_id, int comp_id, msgqueue_param_t *msgqueue) +void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue) { cachemodel_param_t *cachemodel; index_param_t *codeidx; faixbox_param_t *precpacket; message_param_t *msg; - Byte8_t nmax; - + Byte8_t nmax, binOffset, binLength; + int layer_id, numOflayers; + cachemodel = msgqueue->cachemodel; codeidx = cachemodel->target->codeidx; precpacket = codeidx->precpacket[ comp_id]; + numOflayers = codeidx->COD.numOflayers; nmax = get_nmax(precpacket); + if( layers < 0) + layers = numOflayers; + + binOffset = 0; + for( layer_id = 0; layer_id < layers; layer_id++){ + + binLength = get_elemLen( precpacket, seq_id*numOflayers+layer_id, tile_id); + + if( !cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id*numOflayers+layer_id]){ - if( !cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id]){ - msg = (message_param_t *)malloc( sizeof(message_param_t)); - msg->last_byte = true; - msg->in_class_id = comp_precinct_id( tile_id, comp_id, seq_id, codeidx->SIZ.Csiz, codeidx->SIZ.XTnum * codeidx->SIZ.YTnum); - msg->class_id = PRECINCT_MSG; - msg->csn = cachemodel->target->csn; - msg->bin_offset = 0; - msg->length = get_elemLen( precpacket, seq_id, tile_id); - msg->aux = 0; - msg->res_offset = codeidx->offset+get_elemOff( precpacket, seq_id, tile_id); - msg->phld = NULL; - msg->next = NULL; + msg = (message_param_t *)malloc( sizeof(message_param_t)); + msg->last_byte = (layer_id == (numOflayers-1)); + msg->in_class_id = comp_precinct_id( tile_id, comp_id, seq_id, codeidx->SIZ.Csiz, codeidx->SIZ.XTnum * codeidx->SIZ.YTnum); + msg->class_id = PRECINCT_MSG; + msg->csn = cachemodel->target->csn; + msg->bin_offset = binOffset; + msg->length = binLength; + msg->aux = 0; + msg->res_offset = codeidx->offset+get_elemOff( precpacket, seq_id*numOflayers+layer_id, tile_id); + msg->phld = NULL; + msg->next = NULL; - enqueue_message( msg, msgqueue); - cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id] = true; + enqueue_message( msg, msgqueue); + + cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id*numOflayers+layer_id] = true; + } + binOffset += binLength; } } diff --git a/applications/jpip/libopenjpip/msgqueue_manager.h b/applications/jpip/libopenjpip/msgqueue_manager.h index d75a5518..7236d89c 100644 --- a/applications/jpip/libopenjpip/msgqueue_manager.h +++ b/applications/jpip/libopenjpip/msgqueue_manager.h @@ -129,9 +129,10 @@ void enqueue_tile( int tile_id, int level, msgqueue_param_t *msgqueue); * @param[in] seq_id precinct sequence number within its tile * @param[in] tile_id tile index * @param[in] comp_id component number + * @param[in] layers num of layers * @param[in,out] msgqueue message queue */ -void enqueue_precinct( int seq_id, int tile_id, int comp_id, msgqueue_param_t *msgqueue); +void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue); /** diff --git a/applications/jpip/opj_client/opj_dec_server/CMakeLists.txt b/applications/jpip/opj_client/opj_dec_server/CMakeLists.txt index 56c4c7af..10e9aa5c 100644 --- a/applications/jpip/opj_client/opj_dec_server/CMakeLists.txt +++ b/applications/jpip/opj_client/opj_dec_server/CMakeLists.txt @@ -5,6 +5,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/opj_dec_server.c ${CMAKE_CURRENT_SOURCE_DIR}/jp2k_decoder.c ${CMAKE_CURRENT_SOURCE_DIR}/imgsock_manager.c ${CMAKE_CURRENT_SOURCE_DIR}/jpipstream_manager.c +${CMAKE_CURRENT_SOURCE_DIR}/dec_clientmsg_handler.c ) INCLUDE_DIRECTORIES( diff --git a/applications/jpip/opj_client/opj_dec_server/Makefile.am b/applications/jpip/opj_client/opj_dec_server/Makefile.am index 96c10ebe..b9e32c92 100644 --- a/applications/jpip/opj_client/opj_dec_server/Makefile.am +++ b/applications/jpip/opj_client/opj_dec_server/Makefile.am @@ -20,10 +20,12 @@ cache_manager.h \ imgsock_manager.c \ imgsock_manager.h \ jp2k_decoder.c \ +dec_clientmsg_handler.c \ +dec_clientmsg_handler.h \ jp2k_decoder.h \ jpipstream_manager.c \ jpipstream_manager.h \ -opj_dec_server.c +opj_dec_server.c install-data-hook: diff --git a/applications/jpip/opj_client/opj_dec_server/Makefile.nix b/applications/jpip/opj_client/opj_dec_server/Makefile.nix index dd8e06cf..b29671f2 100644 --- a/applications/jpip/opj_client/opj_dec_server/Makefile.nix +++ b/applications/jpip/opj_client/opj_dec_server/Makefile.nix @@ -10,7 +10,8 @@ ALL = opj_dec_server all: $(ALL) -opj_dec_server: opj_dec_server.o jp2k_decoder.o imgsock_manager.o jpipstream_manager.o cache_manager.o $(LIBFNAME) - $(CC) $(CFLAGS) $< jp2k_decoder.o imgsock_manager.o jpipstream_manager.o cache_manager.o $(LDFLAGS) $(LIBFNAME) -o $@ +opj_dec_server: opj_dec_server.o jp2k_decoder.o imgsock_manager.o jpipstream_manager.o cache_manager.o dec_clientmsg_handler.o $(LIBFNAME) + $(CC) $(CFLAGS) $< jp2k_decoder.o imgsock_manager.o jpipstream_manager.o cache_manager.o dec_clientmsg_handler.o $(LDFLAGS) $(LIBFNAME) -o $@ + clean: rm -f $(ALL) *.o *~ diff --git a/applications/jpip/opj_client/opj_dec_server/dec_clientmsg_handler.c b/applications/jpip/opj_client/opj_dec_server/dec_clientmsg_handler.c new file mode 100644 index 00000000..e7b64ee4 --- /dev/null +++ b/applications/jpip/opj_client/opj_dec_server/dec_clientmsg_handler.c @@ -0,0 +1,307 @@ +/* + * $Id$ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2010-2011, Kaori Hagihara + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "dec_clientmsg_handler.h" +#include "ihdrbox_manager.h" +#include "jpipstream_manager.h" +#include "jp2k_encoder.h" + + +//! maximum length of channel identifier +#define MAX_LENOFCID 30 + +/** + * handle JPT- JPP- stream message + * + * @param[in] connected_socket socket descriptor + * @param[in] cachelist cache list pointer + * @param[in,out] jpipstream address of JPT- JPP- stream pointer + * @param[in,out] streamlen address of stream length + * @param[in,out] msgqueue message queue pointer + */ +void handle_JPIPstreamMSG( SOCKET connected_socket, cachelist_param_t *cachelist, Byte_t **jpipstream, int *streamlen, msgqueue_param_t *msgqueue); + +/** + * handle PNM request message + * + * @param[in] connected_socket socket descriptor + * @param[in] jpipstream jpipstream pointer + * @param[in] msgqueue message queue pointer + * @param[in] cachelist cache list pointer + */ +void handle_PNMreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist); + +/** + * handle XML request message + * + * @param[in] connected_socket socket descriptor + * @param[in] jpipstream address of caching jpipstream pointer + * @param[in] cachelist cache list pointer + */ +void handle_XMLreqMSG( SOCKET connected_socket, Byte_t *jpipstream, cachelist_param_t *cachelist); + +/** + * handle TargetID request message + * + * @param[in] connected_socket socket descriptor + * @param[in] cachelist cache list pointer + */ +void handle_TIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist); + +/** + * handle ChannelID request message + * + * @param[in] connected_socket socket descriptor + * @param[in] cachelist cache list pointer + */ +void handle_CIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist); + +/** + * handle distroy ChannelID message + * + * @param[in] connected_socket socket descriptor + * @param[in,out] cachelist cache list pointer + */ +void handle_dstCIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist); + +/** + * handle saving JP2 file request message + * + * @param[in] connected_socket socket descriptor + * @param[in] cachelist cache list pointer + * @param[in] msgqueue message queue pointer + * @param[in] jpipstream address of caching jpipstream pointer + */ +void handle_JP2saveMSG( SOCKET connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jpipstream); + +bool handle_clientmsg( SOCKET connected_socket, cachelist_param_t *cachelist, Byte_t **jpipstream, int *streamlen, msgqueue_param_t *msgqueue) +{ + bool quit = false; + msgtype_t msgtype = identify_clientmsg( connected_socket); + + switch( msgtype){ + case JPIPSTREAM: + handle_JPIPstreamMSG( connected_socket, cachelist, jpipstream, streamlen, msgqueue); + break; + + case PNMREQ: + handle_PNMreqMSG( connected_socket, *jpipstream, msgqueue, cachelist); + break; + + case XMLREQ: + handle_XMLreqMSG( connected_socket, *jpipstream, cachelist); + break; + + case TIDREQ: + handle_TIDreqMSG( connected_socket, cachelist); + break; + + case CIDREQ: + handle_CIDreqMSG( connected_socket, cachelist); + break; + + case CIDDST: + handle_dstCIDreqMSG( connected_socket, cachelist); + break; + + case JP2SAVE: + handle_JP2saveMSG( connected_socket, cachelist, msgqueue, *jpipstream); + break; + + case QUIT: + quit = true; + save_codestream( *jpipstream, *streamlen, "jpt"); + break; + case MSGERROR: + break; + } + + printf("\t end of the connection\n\n"); + if( close_socket(connected_socket) != 0){ + perror("close"); + return false; + } + if( quit) + return false; + + return true; +} + + +void handle_JPIPstreamMSG( SOCKET connected_socket, cachelist_param_t *cachelist, + Byte_t **jpipstream, int *streamlen, msgqueue_param_t *msgqueue) +{ + Byte_t *newjpipstream; + int newstreamlen = 0; + cache_param_t *cache; + char target[MAX_LENOFTARGET], tid[MAX_LENOFTID], cid[MAX_LENOFCID]; + metadatalist_param_t *metadatalist; + + newjpipstream = receive_JPIPstream( connected_socket, target, tid, cid, &newstreamlen); + + parse_JPIPstream( newjpipstream, newstreamlen, *streamlen, msgqueue); + + *jpipstream = update_JPIPstream( newjpipstream, newstreamlen, *jpipstream, streamlen); + free( newjpipstream); + + metadatalist = gene_metadatalist(); + parse_metamsg( msgqueue, *jpipstream, *streamlen, metadatalist); + + // cid registration + if( target[0] != 0){ + if((cache = search_cache( target, cachelist))){ + if( tid[0] != 0) + update_cachetid( tid, cache); + if( cid[0] != 0) + add_cachecid( cid, cache); + } + else{ + cache = gene_cache( target, msgqueue->last->csn, tid, cid); + insert_cache_into_list( cache, cachelist); + } + } + else + cache = search_cacheBycsn( msgqueue->last->csn, cachelist); + + if( cache->metadatalist) + delete_metadatalist( &cache->metadatalist); + cache->metadatalist = metadatalist; + + response_signal( connected_socket, true); +} + +void handle_PNMreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist) +{ + Byte_t *pnmstream; + ihdrbox_param_t *ihdrbox; + char cid[MAX_LENOFCID], tmp[10]; + cache_param_t *cache; + int fw, fh; + + receive_line( connected_socket, cid); + if(!(cache = search_cacheBycid( cid, cachelist))) + if(!(cache = search_cacheBytid( cid, cachelist))) + return; + + receive_line( connected_socket, tmp); + fw = atoi( tmp); + + receive_line( connected_socket, tmp); + fh = atoi( tmp); + + pnmstream = jpipstream_to_pnm( jpipstream, msgqueue, cache->csn, fw, fh, &cache->ihdrbox); + ihdrbox = cache->ihdrbox; + + send_PNMstream( connected_socket, pnmstream, ihdrbox->width, ihdrbox->height, ihdrbox->nc, ihdrbox->bpc > 8 ? 255 : (1 << ihdrbox->bpc) - 1); + + free( pnmstream); +} + +void handle_XMLreqMSG( SOCKET connected_socket, Byte_t *jpipstream, cachelist_param_t *cachelist) +{ + char cid[MAX_LENOFCID]; + cache_param_t *cache; + + receive_line( connected_socket, cid); + if(!(cache = search_cacheBycid( cid, cachelist))) + return; + + boxcontents_param_t *boxcontents = cache->metadatalist->last->boxcontents; + Byte_t *xmlstream = (Byte_t *)malloc( boxcontents->length); + memcpy( xmlstream, jpipstream+boxcontents->offset, boxcontents->length); + send_XMLstream( connected_socket, xmlstream, boxcontents->length); + free( xmlstream); +} + +void handle_TIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist) +{ + char target[MAX_LENOFTARGET], *tid = NULL; + cache_param_t *cache; + int tidlen = 0; + + receive_line( connected_socket, target); + cache = search_cache( target, cachelist); + + if( cache){ + tid = cache->tid; + tidlen = strlen(tid); + } + send_TIDstream( connected_socket, tid, tidlen); +} + +void handle_CIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist) +{ + char target[MAX_LENOFTARGET], *cid = NULL; + cache_param_t *cache; + int cidlen = 0; + + receive_line( connected_socket, target); + cache = search_cache( target, cachelist); + + if( cache){ + if( cache->numOfcid > 0){ + cid = cache->cid[ cache->numOfcid-1]; + cidlen = strlen(cid); + } + } + send_CIDstream( connected_socket, cid, cidlen); +} + +void handle_dstCIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist) +{ + char cid[MAX_LENOFCID]; + + receive_line( connected_socket, cid); + remove_cachecid( cid, cachelist); + response_signal( connected_socket, true); +} + +void handle_JP2saveMSG( SOCKET connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jpipstream) +{ + char cid[MAX_LENOFCID]; + cache_param_t *cache; + Byte_t *jp2stream; + Byte8_t jp2len; + + receive_line( connected_socket, cid); + if(!(cache = search_cacheBycid( cid, cachelist))) + return; + + jp2stream = recons_jp2( msgqueue, jpipstream, cache->csn, &jp2len); + + if( jp2stream){ + save_codestream( jp2stream, jp2len, "jp2"); + free( jp2stream); + } +} diff --git a/applications/jpip/opj_client/opj_dec_server/dec_clientmsg_handler.h b/applications/jpip/opj_client/opj_dec_server/dec_clientmsg_handler.h new file mode 100644 index 00000000..0170c164 --- /dev/null +++ b/applications/jpip/opj_client/opj_dec_server/dec_clientmsg_handler.h @@ -0,0 +1,53 @@ +/* + * $Id$ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2010-2011, Kaori Hagihara + * Copyright (c) 2011, Lucian Corlaciu, GSoC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DEC_CLIENTMSG_HANDLER_H_ +# define DEC_CLIENTMSG_HANDLER_H_ + +#include "bool.h" +#include "imgsock_manager.h" +#include "cache_manager.h" +#include "byte_manager.h" +#include "msgqueue_manager.h" + +/** + * handle client message + * + * @param[in] connected_socket socket descriptor + * @param[in] cachelist cache list pointer + * @param[in,out] jpipstream address of JPT- JPP- stream pointer + * @param[in,out] streamlen address of stream length + * @param[in,out] msgqueue message queue pointer + */ +bool handle_clientmsg( SOCKET connected_socket, cachelist_param_t *cachelist, Byte_t **jpipstream, int *streamlen, msgqueue_param_t *msgqueue); + + +#endif /* !DEC_CLIENTMSG_HANDLER_H_ */ diff --git a/applications/jpip/opj_client/opj_dec_server/imgsock_manager.c b/applications/jpip/opj_client/opj_dec_server/imgsock_manager.c index 4e6652ac..ccc2b04c 100644 --- a/applications/jpip/opj_client/opj_dec_server/imgsock_manager.c +++ b/applications/jpip/opj_client/opj_dec_server/imgsock_manager.c @@ -56,7 +56,7 @@ SOCKET open_listeningsocket() struct sockaddr_in sin; int sock_optval = 1; int port = 5000; - + listening_socket = socket(AF_INET, SOCK_STREAM, 0); if ( listening_socket == -1 ){ perror("socket"); @@ -76,13 +76,13 @@ SOCKET open_listeningsocket() if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){ perror("bind"); - closesocket(listening_socket); + close_socket(listening_socket); exit(1); } if( listen(listening_socket, SOMAXCONN) == -1){ perror("listen"); - closesocket(listening_socket); + close_socket(listening_socket); exit(1); } printf("port %d is listened\n", port); @@ -90,6 +90,14 @@ SOCKET open_listeningsocket() return listening_socket; } +SOCKET accept_socket( SOCKET listening_socket) +{ + struct sockaddr_in peer_sin; + unsigned int addrlen = sizeof(peer_sin); + + return accept( listening_socket, (struct sockaddr *)&peer_sin, &addrlen); +} + msgtype_t identify_clientmsg( SOCKET connected_socket) { int receive_size; @@ -285,3 +293,12 @@ void response_signal( SOCKET connected_socket, bool succeed) if( send( connected_socket, &code, 1, 0) != 1) fprintf( stderr, "Response signalling error\n"); } + +int close_socket( SOCKET sock) +{ +#ifdef _WIN32 + return closesocket( sock); +#else + return close( sock); +#endif +} diff --git a/applications/jpip/opj_client/opj_dec_server/imgsock_manager.h b/applications/jpip/opj_client/opj_dec_server/imgsock_manager.h index 713c099e..bb8e1bcf 100644 --- a/applications/jpip/opj_client/opj_dec_server/imgsock_manager.h +++ b/applications/jpip/opj_client/opj_dec_server/imgsock_manager.h @@ -38,7 +38,6 @@ #include <winsock2.h> #else typedef int SOCKET; -#define closesocket close #endif //_WIN32 /** @@ -48,6 +47,15 @@ typedef int SOCKET; */ SOCKET open_listeningsocket(); +/** + * accept a new connection to the listenning socket + * + * @param listening_socket listenning socket + * @return connected socket (-1 if error occurs) + */ +SOCKET accept_socket( SOCKET listening_socket); + + #define NUM_OF_MSGTYPES 8 typedef enum eMSGTYPE{ JPIPSTREAM, PNMREQ, XMLREQ, TIDREQ, CIDREQ, CIDDST, JP2SAVE, QUIT, MSGERROR} msgtype_t; @@ -125,8 +133,16 @@ void response_signal( SOCKET connected_socket, bool succeed); * @param [out] buf string to be stored * @return red size */ - int receive_line(SOCKET connected_socket, char *buf); + +/** + * close socket + * + * @param [in] sock closing socket + * @return 0 if succeed, -1 if failed + */ +int close_socket( SOCKET sock); + #endif /* !IMGSOCK_MANAGER_H_ */ /*! \file diff --git a/applications/jpip/opj_client/opj_dec_server/opj_dec_server.c b/applications/jpip/opj_client/opj_dec_server/opj_dec_server.c index 5786397e..6e8957a2 100644 --- a/applications/jpip/opj_client/opj_dec_server/opj_dec_server.c +++ b/applications/jpip/opj_client/opj_dec_server/opj_dec_server.c @@ -46,102 +46,23 @@ #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include <unistd.h> +#include "dec_clientmsg_handler.h" +#include "imgsock_manager.h" #include "byte_manager.h" #include "msgqueue_manager.h" -#include "ihdrbox_manager.h" -#include "imgsock_manager.h" -#include "jpipstream_manager.h" #include "cache_manager.h" -#include "jp2k_encoder.h" + #ifdef _WIN32 WSADATA initialisation_win32; -#else -#include <sys/socket.h> -#include <sys/types.h> -#include <netinet/in.h> -#endif //_WIN32 - -//! maximum length of target name -#define MAX_LENOFTARGET 128 - -//! maximum length of channel identifier -#define MAX_LENOFCID 30 - -/** - * handle JPT- JPP- stream message - * - * @param[in] connected_socket socket descriptor - * @param[in] cachelist cache list pointer - * @param[in,out] jpipstream address of JPT- JPP- stream pointer - * @param[in,out] streamlen address of stream length - * @param[in,out] msgqueue message queue pointer - */ -void handle_JPIPstreamMSG( SOCKET connected_socket, cachelist_param_t *cachelist, Byte_t **jpipstream, int *streamlen, msgqueue_param_t *msgqueue); - -/** - * handle PNM request message - * - * @param[in] connected_socket socket descriptor - * @param[in] jpipstream jpipstream pointer - * @param[in] msgqueue message queue pointer - * @param[in] cachelist cache list pointer - */ -void handle_PNMreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist); - -/** - * handle XML request message - * - * @param[in] connected_socket socket descriptor - * @param[in] jpipstream address of caching jpipstream pointer - * @param[in] cachelist cache list pointer - */ -void handle_XMLreqMSG( SOCKET connected_socket, Byte_t *jpipstream, cachelist_param_t *cachelist); - -/** - * handle TargetID request message - * - * @param[in] connected_socket socket descriptor - * @param[in] cachelist cache list pointer - */ -void handle_TIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist); - -/** - * handle ChannelID request message - * - * @param[in] connected_socket socket descriptor - * @param[in] cachelist cache list pointer - */ -void handle_CIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist); - -/** - * handle distroy ChannelID message - * - * @param[in] connected_socket socket descriptor - * @param[in,out] cachelist cache list pointer - */ -void handle_dstCIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist); - -/** - * handle saving JP2 file request message - * - * @param[in] connected_socket socket descriptor - * @param[in] cachelist cache list pointer - * @param[in] msgqueue message queue pointer - * @param[in] jpipstream address of caching jpipstream pointer - */ -void handle_JP2saveMSG( SOCKET connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jpipstream); +#endif int main(int argc, char *argv[]){ - + SOCKET connected_socket; - struct sockaddr_in peer_sin; Byte_t *jpipstream = NULL; int jpipstreamlen = 0; msgqueue_param_t *msgqueue = gene_msgqueue( true, NULL); - bool quit = false; #ifdef _WIN32 int erreur = WSAStartup(MAKEWORD(2,2),&initialisation_win32); @@ -151,60 +72,15 @@ int main(int argc, char *argv[]){ printf( "Initialisation Winsock\n"); #endif //_WIN32 - int listening_socket = open_listeningsocket(); + SOCKET listening_socket = open_listeningsocket(); - unsigned int addrlen = sizeof(peer_sin); - cachelist_param_t *cachelist = gene_cachelist(); - while(( connected_socket = accept(listening_socket, (struct sockaddr *)&peer_sin, &addrlen))!=-1 ){ - msgtype_t msgtype = identify_clientmsg( connected_socket); - - switch( msgtype){ - case JPIPSTREAM: - handle_JPIPstreamMSG( connected_socket, cachelist, &jpipstream, &jpipstreamlen, msgqueue); - break; - - case PNMREQ: - handle_PNMreqMSG( connected_socket, jpipstream, msgqueue, cachelist); - break; - - case XMLREQ: - handle_XMLreqMSG( connected_socket, jpipstream, cachelist); - break; - - case TIDREQ: - handle_TIDreqMSG( connected_socket, cachelist); - break; - - case CIDREQ: - handle_CIDreqMSG( connected_socket, cachelist); - break; - - case CIDDST: - handle_dstCIDreqMSG( connected_socket, cachelist); - break; - - case JP2SAVE: - handle_JP2saveMSG( connected_socket, cachelist, msgqueue, jpipstream); - break; - - case QUIT: - quit = true; - break; - case MSGERROR: - break; - } - - printf("\t end of the connection\n\n"); - if( closesocket(connected_socket) != 0){ - perror("close"); - return -1; - } - if( quit) + while(( connected_socket = accept_socket( listening_socket)) != -1 ) + if(!(handle_clientmsg( connected_socket, cachelist, &jpipstream, &jpipstreamlen, msgqueue))) break; - } - if( closesocket(listening_socket) != 0){ + + if( close_socket(listening_socket) != 0){ perror("close"); return -1; } @@ -214,7 +90,6 @@ int main(int argc, char *argv[]){ if( msgqueue) delete_msgqueue( &msgqueue); - //save_codestream( jpipstream, jpipstreamlen, "jpt"); free( jpipstream); #ifdef _WIN32 @@ -227,150 +102,3 @@ int main(int argc, char *argv[]){ return 0; } - -void handle_JPIPstreamMSG( SOCKET connected_socket, cachelist_param_t *cachelist, - Byte_t **jpipstream, int *streamlen, msgqueue_param_t *msgqueue) -{ - Byte_t *newjpipstream; - int newstreamlen = 0; - cache_param_t *cache; - char target[MAX_LENOFTARGET], tid[MAX_LENOFTID], cid[MAX_LENOFCID]; - metadatalist_param_t *metadatalist; - - newjpipstream = receive_JPIPstream( connected_socket, target, tid, cid, &newstreamlen); - - parse_JPIPstream( newjpipstream, newstreamlen, *streamlen, msgqueue); - - *jpipstream = update_JPIPstream( newjpipstream, newstreamlen, *jpipstream, streamlen); - free( newjpipstream); - - metadatalist = gene_metadatalist(); - parse_metamsg( msgqueue, *jpipstream, *streamlen, metadatalist); - - // cid registration - if( target[0] != 0){ - if((cache = search_cache( target, cachelist))){ - if( tid[0] != 0) - update_cachetid( tid, cache); - if( cid[0] != 0) - add_cachecid( cid, cache); - } - else{ - cache = gene_cache( target, msgqueue->last->csn, tid, cid); - insert_cache_into_list( cache, cachelist); - } - } - else - cache = search_cacheBycsn( msgqueue->last->csn, cachelist); - - if( cache->metadatalist) - delete_metadatalist( &cache->metadatalist); - cache->metadatalist = metadatalist; - - response_signal( connected_socket, true); -} - -void handle_PNMreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist) -{ - Byte_t *pnmstream; - ihdrbox_param_t *ihdrbox; - char cid[MAX_LENOFCID], tmp[10]; - cache_param_t *cache; - int fw, fh; - - receive_line( connected_socket, cid); - if(!(cache = search_cacheBycid( cid, cachelist))) - if(!(cache = search_cacheBytid( cid, cachelist))) - return; - - receive_line( connected_socket, tmp); - fw = atoi( tmp); - - receive_line( connected_socket, tmp); - fh = atoi( tmp); - - pnmstream = jpipstream_to_pnm( jpipstream, msgqueue, cache->csn, fw, fh, &cache->ihdrbox); - ihdrbox = cache->ihdrbox; - - send_PNMstream( connected_socket, pnmstream, ihdrbox->width, ihdrbox->height, ihdrbox->nc, ihdrbox->bpc > 8 ? 255 : (1 << ihdrbox->bpc) - 1); - - free( pnmstream); -} - -void handle_XMLreqMSG( SOCKET connected_socket, Byte_t *jpipstream, cachelist_param_t *cachelist) -{ - char cid[MAX_LENOFCID]; - cache_param_t *cache; - - receive_line( connected_socket, cid); - if(!(cache = search_cacheBycid( cid, cachelist))) - return; - - boxcontents_param_t *boxcontents = cache->metadatalist->last->boxcontents; - Byte_t *xmlstream = (Byte_t *)malloc( boxcontents->length); - memcpy( xmlstream, jpipstream+boxcontents->offset, boxcontents->length); - send_XMLstream( connected_socket, xmlstream, boxcontents->length); - free( xmlstream); -} - -void handle_TIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist) -{ - char target[MAX_LENOFTARGET], *tid = NULL; - cache_param_t *cache; - int tidlen = 0; - - receive_line( connected_socket, target); - cache = search_cache( target, cachelist); - - if( cache){ - tid = cache->tid; - tidlen = strlen(tid); - } - send_TIDstream( connected_socket, tid, tidlen); -} - -void handle_CIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist) -{ - char target[MAX_LENOFTARGET], *cid = NULL; - cache_param_t *cache; - int cidlen = 0; - - receive_line( connected_socket, target); - cache = search_cache( target, cachelist); - - if( cache){ - if( cache->numOfcid > 0){ - cid = cache->cid[ cache->numOfcid-1]; - cidlen = strlen(cid); - } - } - send_CIDstream( connected_socket, cid, cidlen); -} - -void handle_dstCIDreqMSG( SOCKET connected_socket, cachelist_param_t *cachelist) -{ - char cid[MAX_LENOFCID]; - - receive_line( connected_socket, cid); - remove_cachecid( cid, cachelist); - response_signal( connected_socket, true); -} - -void handle_JP2saveMSG( SOCKET connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jpipstream) -{ - char cid[MAX_LENOFCID]; - cache_param_t *cache; - Byte_t *jp2stream; - Byte8_t jp2len; - - receive_line( connected_socket, cid); - if(!(cache = search_cacheBycid( cid, cachelist))) - return; - - jp2stream = recons_jp2( msgqueue, jpipstream, cache->csn, &jp2len); - - if( jp2stream){ - save_codestream( jp2stream, jp2len, "jp2"); - free( jp2stream); - } -} diff --git a/applications/jpip/opj_client/opj_viewer/dist/opj_viewer-20111018.jar b/applications/jpip/opj_client/opj_viewer/dist/opj_viewer-20111018.jar Binary files differnew file mode 100644 index 00000000..a17ca3b6 --- /dev/null +++ b/applications/jpip/opj_client/opj_viewer/dist/opj_viewer-20111018.jar diff --git a/applications/jpip/opj_client/opj_viewer/dist/opj_viewer.jar b/applications/jpip/opj_client/opj_viewer/dist/opj_viewer.jar index 2c3fead7..b135bb0f 120000 --- a/applications/jpip/opj_client/opj_viewer/dist/opj_viewer.jar +++ b/applications/jpip/opj_client/opj_viewer/dist/opj_viewer.jar @@ -1 +1 @@ -opj_viewer-20111007.jar
\ No newline at end of file +opj_viewer-20111018.jar
\ No newline at end of file diff --git a/applications/jpip/opj_server/CMakeLists.txt b/applications/jpip/opj_server/CMakeLists.txt index 29007e1b..e0ed5469 100644 --- a/applications/jpip/opj_server/CMakeLists.txt +++ b/applications/jpip/opj_server/CMakeLists.txt @@ -10,6 +10,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/opj_server.c ${CMAKE_CURRENT_SOURCE_DIR}/query_parser.c ${CMAKE_CURRENT_SOURCE_DIR}/channel_manager.c ${CMAKE_CURRENT_SOURCE_DIR}/session_manager.c +${CMAKE_CURRENT_SOURCE_DIR}/jpip_parser.c ) # Build executable diff --git a/applications/jpip/opj_server/Makefile.am b/applications/jpip/opj_server/Makefile.am index 9fa75b79..cb03c9ce 100644 --- a/applications/jpip/opj_server/Makefile.am +++ b/applications/jpip/opj_server/Makefile.am @@ -18,9 +18,11 @@ channel_manager.c \ opj_server.c \ query_parser.c \ session_manager.c \ +jpip_parser.c \ channel_manager.h \ query_parser.h \ -session_manager.h +session_manager.h \ +jpip_parser.h install-data-hook: @echo -e " (B)\t$(bindir)/opj_server$(EXEEXT)" >> $(top_builddir)/report.txt diff --git a/applications/jpip/opj_server/Makefile.nix b/applications/jpip/opj_server/Makefile.nix index 3df9a6ee..ac2389b4 100644 --- a/applications/jpip/opj_server/Makefile.nix +++ b/applications/jpip/opj_server/Makefile.nix @@ -8,8 +8,8 @@ ALL = opj_server all: $(ALL) -opj_server: opj_server.o query_parser.o channel_manager.o session_manager.o $(LIBFNAME) - $(CC) $(CFLAGS) $< query_parser.o channel_manager.o session_manager.o $(LDFLAGS) -o $@ +opj_server: opj_server.o query_parser.o channel_manager.o session_manager.o jpip_parser.o $(LIBFNAME) + $(CC) $(CFLAGS) $< query_parser.o channel_manager.o session_manager.o jpip_parser.o $(LDFLAGS) -o $@ clean: rm -f $(ALL) *.o *~ diff --git a/applications/jpip/opj_server/jpip_parser.c b/applications/jpip/opj_server/jpip_parser.c new file mode 100644 index 00000000..9b49a362 --- /dev/null +++ b/applications/jpip/opj_server/jpip_parser.c @@ -0,0 +1,536 @@ +/* + * $Id$ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2010-2011, Kaori Hagihara + * Copyright (c) 2011, Lucian Corlaciu, GSoC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <math.h> +#include "jpip_parser.h" +#include "channel_manager.h" +#include "imgreg_manager.h" + +#ifdef SERVER +#include "fcgi_stdio.h" +#define logstream FCGI_stdout +#else +#define FCGI_stdout stdout +#define FCGI_stderr stderr +#define logstream stderr +#endif //SERVER + +/** + * REQUEST: target identification by target or tid request + * + * @param[in] query_param structured query + * @param[in] targetlist target list pointer + * @param[out] target address of target pointer + * @return if succeeded (true) or failed (false) + */ +bool identify_target( query_param_t query_param, targetlist_param_t *targetlist, target_param_t **target); + +/** + * REQUEST: channel association + * this must be processed before any process + * + * @param[in] query_param structured query + * @param[in] sessionlist session list pointer + * @param[out] cursession address of the associated session pointer + * @param[out] curchannel address of the associated channel pointer + * @return if succeeded (true) or failed (false) + */ +bool associate_channel( query_param_t query_param, + sessionlist_param_t *sessionlist, + session_param_t **cursession, + channel_param_t **curchannel); +/** + * REQUEST: new channel (cnew) assignment + * + * @param[in] query_param structured query + * @param[in] sessionlist session list pointer + * @param[in] target requested target pointer + * @param[in,out] cursession address of the associated/opened session pointer + * @param[in,out] curchannel address of the associated/opened channel pointer + * @return if succeeded (true) or failed (false) + */ +bool open_channel( query_param_t query_param, + sessionlist_param_t *sessionlist, + target_param_t *target, + session_param_t **cursession, + channel_param_t **curchannel); + +/** + * REQUEST: channel close (cclose) + * + * @param[in] query_param structured query + * @param[in] sessionlist session list pointer + * @param[in,out] cursession address of the session pointer of deleting channel + * @param[in,out] curchannel address of the deleting channel pointer + * @return if succeeded (true) or failed (false) + */ +bool close_channel( query_param_t query_param, + sessionlist_param_t *sessionlist, + session_param_t **cursession, + channel_param_t **curchannel); + +/** + * REQUEST: view-window (fsiz) + * + * @param[in] query_param structured query + * @param[in] target requested target pointer + * @param[in,out] cursession associated session pointer + * @param[in,out] curchannel associated channel pointer + * @param[out] msgqueue address of the message queue pointer + * @return if succeeded (true) or failed (false) + */ +bool gene_JPIPstream( query_param_t query_param, + target_param_t *target, + session_param_t *cursession, + channel_param_t *curchannel, + msgqueue_param_t **msgqueue); + +bool parse_JPIPrequest( query_param_t query_param, + sessionlist_param_t *sessionlist, + targetlist_param_t *targetlist, + msgqueue_param_t **msgqueue) +{ + target_param_t *target = NULL; + session_param_t *cursession = NULL; + channel_param_t *curchannel = NULL; + + if( query_param.target[0] != '\0' || query_param.tid[0] != '\0'){ + if( !identify_target( query_param, targetlist, &target)) + return false; + } + + if( query_param.cid[0] != '\0'){ + if( !associate_channel( query_param, sessionlist, &cursession, &curchannel)) + return false; + } + + if( query_param.cnew){ + if( !open_channel( query_param, sessionlist, target, &cursession, &curchannel)) + return false; + } + if( query_param.cclose[0][0] != '\0') + if( !close_channel( query_param, sessionlist, &cursession, &curchannel)) + return false; + + if( (query_param.fx > 0 && query_param.fy > 0) || query_param.box_type[0][0] != 0) + if( !gene_JPIPstream( query_param, target, cursession, curchannel, msgqueue)) + return false; + + return true; +} + +bool identify_target( query_param_t query_param, targetlist_param_t *targetlist, target_param_t **target) +{ + if( query_param.tid[0] !='\0' && strcmp( query_param.tid, "0") != 0 ){ + if( query_param.cid[0] != '\0'){ + fprintf( FCGI_stdout, "Reason: Target can not be specified both through tid and cid\r\n"); + fprintf( FCGI_stdout, "Status: 400\r\n"); + return false; + } + if( ( *target = search_targetBytid( query_param.tid, targetlist))) + return true; + } + + if( query_param.target[0] !='\0') + if( !( *target = search_target( query_param.target, targetlist))) + if(!( *target = gene_target( targetlist, query_param.target))) + return false; + + if( *target){ + fprintf( FCGI_stdout, "JPIP-tid: %s\r\n", (*target)->tid); + return true; + } + else{ + fprintf( FCGI_stdout, "Reason: target not found\r\n"); + fprintf( FCGI_stdout, "Status: 400\r\n"); + return false; + } +} + +bool associate_channel( query_param_t query_param, + sessionlist_param_t *sessionlist, + session_param_t **cursession, + channel_param_t **curchannel) +{ + if( search_session_and_channel( query_param.cid, sessionlist, cursession, curchannel)){ + + if( !query_param.cnew) + set_channel_variable_param( query_param, *curchannel); + } + else{ + fprintf( FCGI_stderr, "Error: process canceled\n"); + return false; + } + return true; +} + +bool open_channel( query_param_t query_param, + sessionlist_param_t *sessionlist, + target_param_t *target, + session_param_t **cursession, + channel_param_t **curchannel) +{ + cachemodel_param_t *cachemodel = NULL; + + if( target){ + if( !(*cursession)) + *cursession = gene_session( sessionlist); + if( !( cachemodel = search_cachemodel( target, (*cursession)->cachemodellist))) + if( !(cachemodel = gene_cachemodel( (*cursession)->cachemodellist, target, query_param.return_type==JPPstream))) + return false; + } + else + if( *curchannel) + cachemodel = (*curchannel)->cachemodel; + + *curchannel = gene_channel( query_param, cachemodel, (*cursession)->channellist); + if( *curchannel == NULL) + return false; + + return true; +} + +bool close_channel( query_param_t query_param, + sessionlist_param_t *sessionlist, + session_param_t **cursession, + channel_param_t **curchannel) +{ + if( query_param.cclose[0][0] =='*'){ +#ifndef SERVER + fprintf( logstream, "local log: close all\n"); +#endif + // all channels associatd with the session will be closed + if( !delete_session( cursession, sessionlist)) + return false; + } + else{ + // check if all entry belonging to the same session + int i=0; + while( query_param.cclose[i][0] !='\0'){ + + // In case of the first entry of close cid + if( *cursession == NULL){ + if( !search_session_and_channel( query_param.cclose[i], sessionlist, cursession, curchannel)) + return false; + } + else // second or more entry of close cid + if( !(*curchannel=search_channel( query_param.cclose[i], (*cursession)->channellist))){ + fprintf( FCGI_stdout, "Reason: Cclose id %s is from another session\r\n", query_param.cclose[i]); + return false; + } + i++; + } + // delete channels + i=0; + while( query_param.cclose[i][0] !='\0'){ + + *curchannel = search_channel( query_param.cclose[i], (*cursession)->channellist); + delete_channel( curchannel, (*cursession)->channellist); + i++; + } + + if( (*cursession)->channellist->first == NULL || (*cursession)->channellist->last == NULL) + // In case of empty session + delete_session( cursession, sessionlist); + } + return true; +} + + +/** + * enqueue tiles or precincts into the message queue + * + * @param[in] query_param structured query + * @param[in] msgqueue message queue pointer + */ +void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue); + +/** + * enqueue metadata bins into the message queue + * + * @param[in] query_param structured query + * @param[in] metadatalist pointer to metadata bin list + * @param[in,out] msgqueue message queue pointer + */ +void enqueue_metabins( query_param_t query_param, metadatalist_param_t *metadatalist, msgqueue_param_t *msgqueue); + + +bool gene_JPIPstream( query_param_t query_param, + target_param_t *target, + session_param_t *cursession, + channel_param_t *curchannel, + msgqueue_param_t **msgqueue) +{ + index_param_t *codeidx; + cachemodel_param_t *cachemodel; + + if( !cursession || !curchannel){ // stateless + if( !target) + return false; + if( !(cachemodel = gene_cachemodel( NULL, target, query_param.return_type==JPPstream))) + return false; + *msgqueue = gene_msgqueue( true, cachemodel); + } + else{ // session + cachemodel = curchannel->cachemodel; + target = cachemodel->target; + *msgqueue = gene_msgqueue( false, cachemodel); + } + + codeidx = target->codeidx; + + if( cachemodel->jppstream) + fprintf( FCGI_stdout, "Content-type: image/jpp-stream\r\n"); + else + fprintf( FCGI_stdout, "Content-type: image/jpt-stream\r\n"); + + if( query_param.layers != -1){ + if( query_param.layers > codeidx->COD.numOflayers){ + fprintf( FCGI_stdout, "JPIP-layers: %d\r\n", codeidx->COD.numOflayers); + query_param.layers = codeidx->COD.numOflayers; + } + } + + //meta + if( query_param.box_type[0][0] != 0 && query_param.len != 0) + enqueue_metabins( query_param, codeidx->metadatalist, *msgqueue); + + // image codestream + if( query_param.fx > 0 && query_param.fy > 0){ + if( !cachemodel->mhead_model && query_param.len != 0) + enqueue_mainheader( *msgqueue); + enqueue_imagedata( query_param, *msgqueue); + } + return true; +} + + +/** + * enqueue precinct data-bins into the queue + * + * @param[in] xmin min x coordinate in the tile at the decomposition level + * @param[in] xmax max x coordinate in the tile at the decomposition level + * @param[in] ymin min y coordinate in the tile at the decomposition level + * @param[in] ymax max y coordinate in the tile at the decomposition level + * @param[in] tile_id tile index + * @param[in] level decomposition level + * @param[in] lastcomp last component number + * @param[in] comps pointer to the array that stores the requested components + * @param[in] layers number of quality layers + * @param[in] msgqueue message queue + * @return + */ +void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int level, int lastcomp, bool *comps, int layers, msgqueue_param_t *msgqueue); + +/** + * enqueue all precincts inside a tile into the queue + * + * @param[in] tile_id tile index + * @param[in] level decomposition level + * @param[in] lastcomp last component number + * @param[in] comps pointer to the array that stores the requested components + * @param[in] layers number of quality layers + * @param[in] msgqueue message queue + * @return + */ +void enqueue_allprecincts( int tile_id, int level, int lastcomp, bool *comps, int layers, msgqueue_param_t *msgqueue); + +void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue) +{ + index_param_t *codeidx; + imgreg_param_t imgreg; + range_param_t tile_Xrange, tile_Yrange; + int u, v, tile_id; + int xmin, xmax, ymin, ymax; + int numOfreslev; + + codeidx = msgqueue->cachemodel->target->codeidx; + + if( !(msgqueue->cachemodel->jppstream) && get_nmax( codeidx->tilepart) == 1) // normally not the case + numOfreslev = 1; + else + numOfreslev = codeidx->COD.numOfdecomp+1; + + imgreg = map_viewin2imgreg( query_param.fx, query_param.fy, + query_param.rx, query_param.ry, query_param.rw, query_param.rh, + codeidx->SIZ.XOsiz, codeidx->SIZ.YOsiz, codeidx->SIZ.Xsiz, codeidx->SIZ.Ysiz, + numOfreslev ); + + if( query_param.len == 0) + return; + + for( u=0, tile_id=0; u<codeidx->SIZ.YTnum; u++){ + tile_Yrange = get_tile_Yrange( codeidx->SIZ, tile_id, imgreg.level); + + for( v=0; v<codeidx->SIZ.XTnum; v++, tile_id++){ + tile_Xrange = get_tile_Xrange( codeidx->SIZ, tile_id, imgreg.level); + + if( tile_Xrange.minvalue < tile_Xrange.maxvalue && tile_Yrange.minvalue < tile_Yrange.maxvalue){ + if( tile_Xrange.maxvalue <= imgreg.xosiz + imgreg.ox || + tile_Xrange.minvalue >= imgreg.xosiz + imgreg.ox + imgreg.sx || + tile_Yrange.maxvalue <= imgreg.yosiz + imgreg.oy || + tile_Yrange.minvalue >= imgreg.yosiz + imgreg.oy + imgreg.sy) { + //printf("Tile completely excluded from view-window %d\n", tile_id); + // Tile completely excluded from view-window + } + else if( tile_Xrange.minvalue >= imgreg.xosiz + imgreg.ox && + tile_Xrange.maxvalue <= imgreg.xosiz + imgreg.ox + imgreg.sx && + tile_Yrange.minvalue >= imgreg.yosiz + imgreg.oy && + tile_Yrange.maxvalue <= imgreg.yosiz + imgreg.oy + imgreg.sy) { + // Tile completely contained within view-window + // high priority + //printf("Tile completely contained within view-window %d\n", tile_id); + if( msgqueue->cachemodel->jppstream){ + enqueue_tileheader( tile_id, msgqueue); + enqueue_allprecincts( tile_id, imgreg.level, query_param.lastcomp, query_param.comps, query_param.layers, msgqueue); + } + else + enqueue_tile( tile_id, imgreg.level, msgqueue); + } + else{ + // Tile partially overlaps view-window + // low priority + //printf("Tile partially overlaps view-window %d\n", tile_id); + if( msgqueue->cachemodel->jppstream){ + enqueue_tileheader( tile_id, msgqueue); + + xmin = tile_Xrange.minvalue >= imgreg.xosiz + imgreg.ox ? 0 : imgreg.xosiz + imgreg.ox - tile_Xrange.minvalue; + xmax = tile_Xrange.maxvalue <= imgreg.xosiz + imgreg.ox + imgreg.sx ? tile_Xrange.maxvalue - tile_Xrange.minvalue -1 : imgreg.xosiz + imgreg.ox + imgreg.sx - tile_Xrange.minvalue -1; + ymin = tile_Yrange.minvalue >= imgreg.yosiz + imgreg.oy ? 0 : imgreg.yosiz + imgreg.oy - tile_Yrange.minvalue; + ymax = tile_Yrange.maxvalue <= imgreg.yosiz + imgreg.oy + imgreg.sy ? tile_Yrange.maxvalue - tile_Yrange.minvalue -1 : imgreg.yosiz + imgreg.oy + imgreg.sy - tile_Yrange.minvalue -1; + enqueue_precincts( xmin, xmax, ymin, ymax, tile_id, imgreg.level, query_param.lastcomp, query_param.comps, query_param.layers, msgqueue); + } + else + enqueue_tile( tile_id, imgreg.level, msgqueue); + } + } + } + } +} + + +void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int level, int lastcomp, bool *comps, int layers, msgqueue_param_t *msgqueue) +{ + index_param_t *codeidx; + int c, u, v, res_lev, dec_lev; + int seq_id; + Byte4_t XTsiz, YTsiz; + Byte4_t XPsiz, YPsiz; + Byte4_t xminP, xmaxP, yminP, ymaxP; + + codeidx = msgqueue->cachemodel->target->codeidx; + + for( c=0; c<codeidx->SIZ.Csiz; c++) + if( lastcomp == -1 /*all*/ || ( c<=lastcomp && comps[c])){ + seq_id = 0; + for( res_lev=0, dec_lev=codeidx->COD.numOfdecomp; dec_lev>=level; res_lev++, dec_lev--){ + + XTsiz = get_tile_XSiz( codeidx->SIZ, tile_id, dec_lev); + YTsiz = get_tile_YSiz( codeidx->SIZ, tile_id, dec_lev); + + XPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.XPsiz[ res_lev] : XTsiz; + YPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.YPsiz[ res_lev] : YTsiz; + + for( u=0; u<ceil((double)YTsiz/(double)YPsiz); u++){ + yminP = u*YPsiz; + ymaxP = (u+1)*YPsiz-1; + if( YTsiz <= ymaxP) + ymaxP = YTsiz-1; + + for( v=0; v<ceil((double)XTsiz/(double)XPsiz); v++, seq_id++){ + xminP = v*XPsiz; + xmaxP = (v+1)*XPsiz-1; + if( XTsiz <= xmaxP) + xmaxP = XTsiz-1; + + if( xmaxP < xmin || xminP > xmax || ymaxP < ymin || yminP > ymax){ + // Precinct completely excluded from view-window + } + else if( xminP >= xmin && xmaxP <= xmax && yminP >= ymin && ymaxP <= ymax){ + // Precinct completely contained within view-window + // high priority + enqueue_precinct( seq_id, tile_id, c, (dec_lev>level)?-1:layers, msgqueue); + } + else{ + // Precinct partially overlaps view-window + // low priority + enqueue_precinct( seq_id, tile_id, c, (dec_lev>level)?-1:layers, msgqueue); + } + } + } + } + } +} + +void enqueue_allprecincts( int tile_id, int level, int lastcomp, bool *comps, int layers, msgqueue_param_t *msgqueue) +{ + index_param_t *codeidx; + int c, i, res_lev, dec_lev; + int seq_id; + Byte4_t XTsiz, YTsiz; + Byte4_t XPsiz, YPsiz; + + codeidx = msgqueue->cachemodel->target->codeidx; + + for( c=0; c<codeidx->SIZ.Csiz; c++) + if( lastcomp == -1 /*all*/ || ( c<=lastcomp && comps[c])){ + seq_id = 0; + for( res_lev=0, dec_lev=codeidx->COD.numOfdecomp; dec_lev>=level; res_lev++, dec_lev--){ + + XTsiz = get_tile_XSiz( codeidx->SIZ, tile_id, dec_lev); + YTsiz = get_tile_YSiz( codeidx->SIZ, tile_id, dec_lev); + + XPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.XPsiz[ res_lev] : XTsiz; + YPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.YPsiz[ res_lev] : YTsiz; + + for( i=0; i<ceil((double)YTsiz/(double)YPsiz)*ceil((double)XTsiz/(double)XPsiz); i++, seq_id++) + enqueue_precinct( seq_id, tile_id, c, (dec_lev>level)?-1:layers, msgqueue); + } + } +} + +void enqueue_metabins( query_param_t query_param, metadatalist_param_t *metadatalist, msgqueue_param_t *msgqueue) +{ + int i; + for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){ + if( query_param.box_type[i][0] == '*'){ + // not implemented + } + else{ + int idx = search_metadataidx( query_param.box_type[i], metadatalist); + + if( idx != -1) + enqueue_metadata( idx, msgqueue); + } + } +} diff --git a/applications/jpip/opj_server/jpip_parser.h b/applications/jpip/opj_server/jpip_parser.h new file mode 100644 index 00000000..bcb5edbf --- /dev/null +++ b/applications/jpip/opj_server/jpip_parser.h @@ -0,0 +1,56 @@ +/* + * $Id$ + * + * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2002-2011, Professor Benoit Macq + * Copyright (c) 2010-2011, Kaori Hagihara + * Copyright (c) 2011, Lucian Corlaciu, GSoC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef JPIP_PARSER_H_ +# define JPIP_PARSER_H_ + +#include "bool.h" +#include "query_parser.h" +#include "session_manager.h" +#include "target_manager.h" +#include "msgqueue_manager.h" + +/** + * parse JPIP request + * + * @param[in] query_param structured query + * @param[in] sessionlist session list pointer + * @param[in] targetlist target list pointer + * @param[in,out] msgqueue address of the message queue pointer + * @return if succeeded (true) or failed (false) + */ +bool parse_JPIPrequest( query_param_t query_param, + sessionlist_param_t *sessionlist, + targetlist_param_t *targetlist, + msgqueue_param_t **msgqueue); + + +#endif /* !JPIP_PARSER_H_ */ diff --git a/applications/jpip/opj_server/opj_server.c b/applications/jpip/opj_server/opj_server.c index a9778cd4..b39ad56e 100644 --- a/applications/jpip/opj_server/opj_server.c +++ b/applications/jpip/opj_server/opj_server.c @@ -51,10 +51,9 @@ #include <math.h> #include "query_parser.h" -#include "channel_manager.h" +#include "jpip_parser.h" #include "session_manager.h" #include "target_manager.h" -#include "imgreg_manager.h" #include "msgqueue_manager.h" #ifndef QUIT_SIGNAL @@ -70,20 +69,6 @@ #define logstream stderr #endif //SERVER -/** - * parse JPIP request - * - * @param[in] query_param structured query - * @param[in] sessionlist session list pointer - * @param[in] targetlist target list pointer - * @param[in,out] msgqueue address of the message queue pointer - * @return if succeeded (true) or failed (false) - */ -bool parse_JPIPrequest( query_param_t query_param, - sessionlist_param_t *sessionlist, - targetlist_param_t *targetlist, - msgqueue_param_t **msgqueue); - int main(void) { sessionlist_param_t *sessionlist; @@ -144,481 +129,3 @@ int main(void) return 0; } - -/** - * REQUEST: target identification by target or tid request - * - * @param[in] query_param structured query - * @param[in] targetlist target list pointer - * @param[out] target address of target pointer - * @return if succeeded (true) or failed (false) - */ -bool identify_target( query_param_t query_param, targetlist_param_t *targetlist, target_param_t **target); - -/** - * REQUEST: channel association - * this must be processed before any process - * - * @param[in] query_param structured query - * @param[in] sessionlist session list pointer - * @param[out] cursession address of the associated session pointer - * @param[out] curchannel address of the associated channel pointer - * @return if succeeded (true) or failed (false) - */ -bool associate_channel( query_param_t query_param, - sessionlist_param_t *sessionlist, - session_param_t **cursession, - channel_param_t **curchannel); -/** - * REQUEST: new channel (cnew) assignment - * - * @param[in] query_param structured query - * @param[in] sessionlist session list pointer - * @param[in] target requested target pointer - * @param[in,out] cursession address of the associated/opened session pointer - * @param[in,out] curchannel address of the associated/opened channel pointer - * @return if succeeded (true) or failed (false) - */ -bool open_channel( query_param_t query_param, - sessionlist_param_t *sessionlist, - target_param_t *target, - session_param_t **cursession, - channel_param_t **curchannel); - -/** - * REQUEST: channel close (cclose) - * - * @param[in] query_param structured query - * @param[in] sessionlist session list pointer - * @param[in,out] cursession address of the session pointer of deleting channel - * @param[in,out] curchannel address of the deleting channel pointer - * @return if succeeded (true) or failed (false) - */ -bool close_channel( query_param_t query_param, - sessionlist_param_t *sessionlist, - session_param_t **cursession, - channel_param_t **curchannel); - -/** - * REQUEST: view-window (fsiz) - * - * @param[in] query_param structured query - * @param[in] target requested target pointer - * @param[in,out] cursession associated session pointer - * @param[in,out] curchannel associated channel pointer - * @param[out] msgqueue address of the message queue pointer - * @return if succeeded (true) or failed (false) - */ -bool gene_JPIPstream( query_param_t query_param, - target_param_t *target, - session_param_t *cursession, - channel_param_t *curchannel, - msgqueue_param_t **msgqueue); - -bool parse_JPIPrequest( query_param_t query_param, - sessionlist_param_t *sessionlist, - targetlist_param_t *targetlist, - msgqueue_param_t **msgqueue) -{ - target_param_t *target = NULL; - session_param_t *cursession = NULL; - channel_param_t *curchannel = NULL; - - if( query_param.target[0] != '\0' || query_param.tid[0] != '\0'){ - if( !identify_target( query_param, targetlist, &target)) - return false; - } - - if( query_param.cid[0] != '\0'){ - if( !associate_channel( query_param, sessionlist, &cursession, &curchannel)) - return false; - } - - if( query_param.cnew){ - if( !open_channel( query_param, sessionlist, target, &cursession, &curchannel)) - return false; - } - if( query_param.cclose[0][0] != '\0') - if( !close_channel( query_param, sessionlist, &cursession, &curchannel)) - return false; - - if( (query_param.fx > 0 && query_param.fy > 0) || query_param.box_type[0][0] != 0) - if( !gene_JPIPstream( query_param, target, cursession, curchannel, msgqueue)) - return false; - - return true; -} - -bool identify_target( query_param_t query_param, targetlist_param_t *targetlist, target_param_t **target) -{ - if( query_param.tid[0] !='\0' && strcmp( query_param.tid, "0") != 0 ){ - if( query_param.cid[0] != '\0'){ - fprintf( FCGI_stdout, "Reason: Target can not be specified both through tid and cid\r\n"); - fprintf( FCGI_stdout, "Status: 400\r\n"); - return false; - } - if( ( *target = search_targetBytid( query_param.tid, targetlist))) - return true; - } - - if( query_param.target[0] !='\0') - if( !( *target = search_target( query_param.target, targetlist))) - if(!( *target = gene_target( targetlist, query_param.target))) - return false; - - if( *target){ - fprintf( FCGI_stdout, "JPIP-tid: %s\r\n", (*target)->tid); - return true; - } - else{ - fprintf( FCGI_stdout, "Reason: target not found\r\n"); - fprintf( FCGI_stdout, "Status: 400\r\n"); - return false; - } -} - -bool associate_channel( query_param_t query_param, - sessionlist_param_t *sessionlist, - session_param_t **cursession, - channel_param_t **curchannel) -{ - if( search_session_and_channel( query_param.cid, sessionlist, cursession, curchannel)){ - - if( !query_param.cnew) - set_channel_variable_param( query_param, *curchannel); - } - else{ - fprintf( FCGI_stderr, "Error: process canceled\n"); - return false; - } - return true; -} - -bool open_channel( query_param_t query_param, - sessionlist_param_t *sessionlist, - target_param_t *target, - session_param_t **cursession, - channel_param_t **curchannel) -{ - cachemodel_param_t *cachemodel = NULL; - - if( target){ - if( !(*cursession)) - *cursession = gene_session( sessionlist); - if( !( cachemodel = search_cachemodel( target, (*cursession)->cachemodellist))) - if( !(cachemodel = gene_cachemodel( (*cursession)->cachemodellist, target, query_param.return_type==JPPstream))) - return false; - } - else - if( *curchannel) - cachemodel = (*curchannel)->cachemodel; - - *curchannel = gene_channel( query_param, cachemodel, (*cursession)->channellist); - if( *curchannel == NULL) - return false; - - return true; -} - -bool close_channel( query_param_t query_param, - sessionlist_param_t *sessionlist, - session_param_t **cursession, - channel_param_t **curchannel) -{ - if( query_param.cclose[0][0] =='*'){ -#ifndef SERVER - fprintf( logstream, "local log: close all\n"); -#endif - // all channels associatd with the session will be closed - if( !delete_session( cursession, sessionlist)) - return false; - } - else{ - // check if all entry belonging to the same session - int i=0; - while( query_param.cclose[i][0] !='\0'){ - - // In case of the first entry of close cid - if( *cursession == NULL){ - if( !search_session_and_channel( query_param.cclose[i], sessionlist, cursession, curchannel)) - return false; - } - else // second or more entry of close cid - if( !(*curchannel=search_channel( query_param.cclose[i], (*cursession)->channellist))){ - fprintf( FCGI_stdout, "Reason: Cclose id %s is from another session\r\n", query_param.cclose[i]); - return false; - } - i++; - } - // delete channels - i=0; - while( query_param.cclose[i][0] !='\0'){ - - *curchannel = search_channel( query_param.cclose[i], (*cursession)->channellist); - delete_channel( curchannel, (*cursession)->channellist); - i++; - } - - if( (*cursession)->channellist->first == NULL || (*cursession)->channellist->last == NULL) - // In case of empty session - delete_session( cursession, sessionlist); - } - return true; -} - - -/** - * enqueue tiles or precincts into the message queue - * - * @param[in] query_param structured query - * @param[in] msgqueue message queue pointer - */ -void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue); - -/** - * enqueue metadata bins into the message queue - * - * @param[in] query_param structured query - * @param[in] metadatalist pointer to metadata bin list - * @param[in,out] msgqueue message queue pointer - */ -void enqueue_metabins( query_param_t query_param, metadatalist_param_t *metadatalist, msgqueue_param_t *msgqueue); - - -bool gene_JPIPstream( query_param_t query_param, - target_param_t *target, - session_param_t *cursession, - channel_param_t *curchannel, - msgqueue_param_t **msgqueue) -{ - index_param_t *codeidx; - cachemodel_param_t *cachemodel; - - if( !cursession || !curchannel){ // stateless - if( !target) - return false; - if( !(cachemodel = gene_cachemodel( NULL, target, query_param.return_type==JPPstream))) - return false; - *msgqueue = gene_msgqueue( true, cachemodel); - } - else{ // session - cachemodel = curchannel->cachemodel; - target = cachemodel->target; - *msgqueue = gene_msgqueue( false, cachemodel); - } - - if( cachemodel->jppstream) - fprintf( FCGI_stdout, "Content-type: image/jpp-stream\r\n"); - else - fprintf( FCGI_stdout, "Content-type: image/jpt-stream\r\n"); - - codeidx = target->codeidx; - - //meta - if( query_param.box_type[0][0] != 0) - enqueue_metabins( query_param, codeidx->metadatalist, *msgqueue); - - // image codestream - if( query_param.fx > 0 && query_param.fy > 0){ - if( !cachemodel->mhead_model) - enqueue_mainheader( *msgqueue); - enqueue_imagedata( query_param, *msgqueue); - } - return true; -} - - -/** - * enqueue precinct data-bins into the queue - * - * @param[in] xmin min x coordinate in the tile at the decomposition level - * @param[in] xmax max x coordinate in the tile at the decomposition level - * @param[in] ymin min y coordinate in the tile at the decomposition level - * @param[in] ymax max y coordinate in the tile at the decomposition level - * @param[in] tile_id tile index - * @param[in] level decomposition level - * @param[in] lastcomp last component number - * @param[in] comps pointer to the array that stores the requested components - * @param[in] msgqueue message queue - * @return - */ -void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int level, int lastcomp, bool *comps, msgqueue_param_t *msgqueue); - -/** - * enqueue all precincts inside a tile into the queue - * - * @param[in] tile_id tile index - * @param[in] level decomposition level - * @param[in] lastcomp last component number - * @param[in] comps pointer to the array that stores the requested components - * @param[in] msgqueue message queue - * @return - */ -void enqueue_allprecincts( int tile_id, int level, int lastcomp, bool *comps, msgqueue_param_t *msgqueue); - -void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue) -{ - index_param_t *codeidx; - imgreg_param_t imgreg; - range_param_t tile_Xrange, tile_Yrange; - int u, v, tile_id; - int xmin, xmax, ymin, ymax; - int numOfreslev; - - codeidx = msgqueue->cachemodel->target->codeidx; - - if( !(msgqueue->cachemodel->jppstream) && get_nmax( codeidx->tilepart) == 1) // normally not the case - numOfreslev = 1; - else - numOfreslev = codeidx->COD.numOfdecomp+1; - - imgreg = map_viewin2imgreg( query_param.fx, query_param.fy, - query_param.rx, query_param.ry, query_param.rw, query_param.rh, - codeidx->SIZ.XOsiz, codeidx->SIZ.YOsiz, codeidx->SIZ.Xsiz, codeidx->SIZ.Ysiz, - numOfreslev ); - - for( u=0, tile_id=0; u<codeidx->SIZ.YTnum; u++){ - tile_Yrange = get_tile_Yrange( codeidx->SIZ, tile_id, imgreg.level); - - for( v=0; v<codeidx->SIZ.XTnum; v++, tile_id++){ - tile_Xrange = get_tile_Xrange( codeidx->SIZ, tile_id, imgreg.level); - - if( tile_Xrange.minvalue < tile_Xrange.maxvalue && tile_Yrange.minvalue < tile_Yrange.maxvalue){ - if( tile_Xrange.maxvalue <= imgreg.xosiz + imgreg.ox || - tile_Xrange.minvalue >= imgreg.xosiz + imgreg.ox + imgreg.sx || - tile_Yrange.maxvalue <= imgreg.yosiz + imgreg.oy || - tile_Yrange.minvalue >= imgreg.yosiz + imgreg.oy + imgreg.sy) { - //printf("Tile completely excluded from view-window %d\n", tile_id); - // Tile completely excluded from view-window - } - else if( tile_Xrange.minvalue >= imgreg.xosiz + imgreg.ox && - tile_Xrange.maxvalue <= imgreg.xosiz + imgreg.ox + imgreg.sx && - tile_Yrange.minvalue >= imgreg.yosiz + imgreg.oy && - tile_Yrange.maxvalue <= imgreg.yosiz + imgreg.oy + imgreg.sy) { - // Tile completely contained within view-window - // high priority - //printf("Tile completely contained within view-window %d\n", tile_id); - if( msgqueue->cachemodel->jppstream){ - enqueue_tileheader( tile_id, msgqueue); - enqueue_allprecincts( tile_id, imgreg.level, query_param.lastcomp, query_param.comps, msgqueue); - } - else - enqueue_tile( tile_id, imgreg.level, msgqueue); - } - else{ - // Tile partially overlaps view-window - // low priority - //printf("Tile partially overlaps view-window %d\n", tile_id); - if( msgqueue->cachemodel->jppstream){ - enqueue_tileheader( tile_id, msgqueue); - - xmin = tile_Xrange.minvalue >= imgreg.xosiz + imgreg.ox ? 0 : imgreg.xosiz + imgreg.ox - tile_Xrange.minvalue; - xmax = tile_Xrange.maxvalue <= imgreg.xosiz + imgreg.ox + imgreg.sx ? tile_Xrange.maxvalue - tile_Xrange.minvalue -1 : imgreg.xosiz + imgreg.ox + imgreg.sx - tile_Xrange.minvalue -1; - ymin = tile_Yrange.minvalue >= imgreg.yosiz + imgreg.oy ? 0 : imgreg.yosiz + imgreg.oy - tile_Yrange.minvalue; - ymax = tile_Yrange.maxvalue <= imgreg.yosiz + imgreg.oy + imgreg.sy ? tile_Yrange.maxvalue - tile_Yrange.minvalue -1 : imgreg.yosiz + imgreg.oy + imgreg.sy - tile_Yrange.minvalue -1; - enqueue_precincts( xmin, xmax, ymin, ymax, tile_id, imgreg.level, query_param.lastcomp, query_param.comps, msgqueue); - } - else - enqueue_tile( tile_id, imgreg.level, msgqueue); - } - } - } - } -} - - -void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int level, int lastcomp, bool *comps, msgqueue_param_t *msgqueue) -{ - index_param_t *codeidx; - int c, u, v, res_lev, dec_lev; - int seq_id; - Byte4_t XTsiz, YTsiz; - Byte4_t XPsiz, YPsiz; - Byte4_t xminP, xmaxP, yminP, ymaxP; - - codeidx = msgqueue->cachemodel->target->codeidx; - - for( c=0; c<codeidx->SIZ.Csiz; c++) - if( lastcomp == -1 /*all*/ || ( c<=lastcomp && comps[c])){ - seq_id = 0; - for( res_lev=0, dec_lev=codeidx->COD.numOfdecomp; dec_lev>=level; res_lev++, dec_lev--){ - - XTsiz = get_tile_XSiz( codeidx->SIZ, tile_id, dec_lev); - YTsiz = get_tile_YSiz( codeidx->SIZ, tile_id, dec_lev); - - XPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.XPsiz[ res_lev] : XTsiz; - YPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.YPsiz[ res_lev] : YTsiz; - - for( u=0; u<ceil((double)YTsiz/(double)YPsiz); u++){ - yminP = u*YPsiz; - ymaxP = (u+1)*YPsiz-1; - if( YTsiz <= ymaxP) - ymaxP = YTsiz-1; - - for( v=0; v<ceil((double)XTsiz/(double)XPsiz); v++, seq_id++){ - xminP = v*XPsiz; - xmaxP = (v+1)*XPsiz-1; - if( XTsiz <= xmaxP) - xmaxP = XTsiz-1; - - if( xmaxP < xmin || xminP > xmax || ymaxP < ymin || yminP > ymax){ - // Precinct completely excluded from view-window - } - else if( xminP >= xmin && xmaxP <= xmax && yminP >= ymin && ymaxP <= ymax){ - // Precinct completely contained within view-window - // high priority - enqueue_precinct( seq_id, tile_id, c, msgqueue); - } - else{ - // Precinct partially overlaps view-window - // low priority - enqueue_precinct( seq_id, tile_id, c, msgqueue); - } - } - } - } - } -} - -void enqueue_allprecincts( int tile_id, int level, int lastcomp, bool *comps, msgqueue_param_t *msgqueue) -{ - index_param_t *codeidx; - int c, i, res_lev, dec_lev; - int seq_id; - Byte4_t XTsiz, YTsiz; - Byte4_t XPsiz, YPsiz; - - codeidx = msgqueue->cachemodel->target->codeidx; - - for( c=0; c<codeidx->SIZ.Csiz; c++) - if( lastcomp == -1 /*all*/ || ( c<=lastcomp && comps[c])){ - seq_id = 0; - for( res_lev=0, dec_lev=codeidx->COD.numOfdecomp; dec_lev>=level; res_lev++, dec_lev--){ - - XTsiz = get_tile_XSiz( codeidx->SIZ, tile_id, dec_lev); - YTsiz = get_tile_YSiz( codeidx->SIZ, tile_id, dec_lev); - - XPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.XPsiz[ res_lev] : XTsiz; - YPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.YPsiz[ res_lev] : YTsiz; - - for( i=0; i<ceil((double)YTsiz/(double)YPsiz)*ceil((double)XTsiz/(double)XPsiz); i++, seq_id++) - enqueue_precinct( seq_id, tile_id, c, msgqueue); - } - } -} - -void enqueue_metabins( query_param_t query_param, metadatalist_param_t *metadatalist, msgqueue_param_t *msgqueue) -{ - int i; - for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){ - if( query_param.box_type[i][0] == '*'){ - // not implemented - } - else{ - int idx = search_metadataidx( query_param.box_type[i], metadatalist); - - if( idx != -1) - enqueue_metadata( idx, msgqueue); - } - } -} diff --git a/applications/jpip/opj_server/query_parser.c b/applications/jpip/opj_server/query_parser.c index 1195dcc5..a29c8f12 100644 --- a/applications/jpip/opj_server/query_parser.c +++ b/applications/jpip/opj_server/query_parser.c @@ -39,6 +39,7 @@ #include <stdio.h> #include <string.h> +#include <stdlib.h> #include "query_parser.h" #ifdef SERVER @@ -116,6 +117,9 @@ void parse_query( char *query_string, query_param_t *query_param) else if( strcasecmp( fieldname, "rsiz") == 0) sscanf( fieldval, "%d,%d", &query_param->rw, &query_param->rh); + else if( strcasecmp( fieldname, "layers") == 0) + sscanf( fieldval, "%d", &query_param->layers); + else if( strcasecmp( fieldname, "cid") == 0) strcpy( query_param->cid, fieldval); @@ -137,6 +141,9 @@ void parse_query( char *query_string, query_param_t *query_param) else if( strncasecmp( fieldval, "jpt-stream", 10) == 0) query_param->return_type = JPTstream; } + + else if( strcasecmp( fieldname, "len") == 0) + sscanf( fieldval, "%d", &query_param->len); } } } @@ -145,18 +152,19 @@ void init_queryparam( query_param_t *query_param) { int i; - query_param->target[0]='\0'; - query_param->tid[0]='\0'; - query_param->fx=-1; - query_param->fy=-1; - query_param->rx=-1; - query_param->ry=-1; - query_param->rw=-1; - query_param->rh=-1; + query_param->target[0] = '\0'; + query_param->tid[0] = '\0'; + query_param->fx = -1; + query_param->fy = -1; + query_param->rx = -1; + query_param->ry = -1; + query_param->rw = -1; + query_param->rh = -1; + query_param->layers = -1; query_param->lastcomp = -1; query_param->comps = NULL; - query_param->cid[0]='\0'; - query_param->cnew=false; + query_param->cid[0] = '\0'; + query_param->cnew = false; memset( query_param->cclose, 0, MAX_NUMOFCCLOSE*MAX_LENOFCID); memset( query_param->box_type, 0, MAX_NUMOFBOX*4); memset( query_param->limit, 0, MAX_NUMOFBOX*sizeof(int)); @@ -171,6 +179,7 @@ void init_queryparam( query_param_t *query_param) query_param->max_depth = -1; query_param->metadata_only = false; query_param->return_type = UNKNOWN; + query_param->len = -1; } @@ -208,6 +217,7 @@ void print_queryparam( query_param_t query_param) fprintf( logstream, "\t tid: %s\n", query_param.tid); fprintf( logstream, "\t fx,fy: %d, %d\n", query_param.fx, query_param.fy); fprintf( logstream, "\t rx,ry: %d, %d \t rw,rh: %d, %d\n", query_param.rx, query_param.ry, query_param.rw, query_param.rh); + fprintf( logstream, "\t layers: %d\n", query_param.layers); fprintf( logstream, "\t components: "); if( query_param.lastcomp == -1) fprintf( logstream, "ALL\n"); @@ -234,6 +244,7 @@ void print_queryparam( query_param_t query_param) fprintf( logstream, "\t max-depth: %d\n", query_param.max_depth); fprintf( logstream, "\t metadata-only: %d\n", query_param.metadata_only); fprintf( logstream, "\t image return type: %d, [JPP-stream=0, JPT-stream=1, UNKNOWN=-1]\n", query_param.return_type); + fprintf( logstream, "\t len: %d\n", query_param.len); } void str2cclose( char *src, char cclose[][MAX_LENOFCID]) diff --git a/applications/jpip/opj_server/query_parser.h b/applications/jpip/opj_server/query_parser.h index 2df9609b..55be9dd1 100644 --- a/applications/jpip/opj_server/query_parser.h +++ b/applications/jpip/opj_server/query_parser.h @@ -58,6 +58,7 @@ typedef struct query_param{ char tid[MAX_LENOFTID]; //!< target identifier int fx, fy; //!< frame size (fx,fy) int rx, ry, rw, rh; //!< roi region + int layers; //!< quality layers int lastcomp; //!< last component number bool *comps; //!< components for jpp-stream, null means all components char cid[MAX_LENOFCID]; //!< channel identifier @@ -74,6 +75,7 @@ typedef struct query_param{ int max_depth; //!< max-depth bool metadata_only; //!< metadata-only request image_return_t return_type; //!< image return type + int len; //!< maximum response length } query_param_t; diff --git a/applications/jpip/tools/jpip_to_j2k.c b/applications/jpip/tools/jpip_to_j2k.c index dfceb69f..9a469e74 100644 --- a/applications/jpip/tools/jpip_to_j2k.c +++ b/applications/jpip/tools/jpip_to_j2k.c @@ -89,6 +89,7 @@ int main(int argc,char *argv[]) //print_msgqueue( msgqueue); + // arguments fw, fh need to be set for LRCP, PCRL, CPRL j2kstream = recons_j2k( msgqueue, jpipstream, msgqueue->first->csn, 0, 0, &j2klen); delete_msgqueue( &msgqueue); |
