diff --git a/applications/jpip/CHANGES b/applications/jpip/CHANGES index ad582949..eca480ae 100644 --- a/applications/jpip/CHANGES +++ b/applications/jpip/CHANGES @@ -5,6 +5,9 @@ What's New for OpenJPIP ! : changed + : added +October 12, 2011 ++ [kaori] enable layers requests; restricting the number of codesream quality layers + October 10, 2011 - [antonin] removed obsolete indexer utility + [kaori] enable JPT-stream request from client viewer option diff --git a/applications/jpip/libopenjpip/j2kheader_manager.c b/applications/jpip/libopenjpip/j2kheader_manager.c index ad94d587..b1b9d7f3 100644 --- a/applications/jpip/libopenjpip/j2kheader_manager.c +++ b/applications/jpip/libopenjpip/j2kheader_manager.c @@ -222,6 +222,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..d379e62d 100644 --- a/applications/jpip/libopenjpip/jp2k_encoder.c +++ b/applications/jpip/libopenjpip/jp2k_encoder.c @@ -221,6 +221,8 @@ Byte_t * recons_codestream_from_JPTstream( msgqueue_param_t *msgqueue, Byte_t *j return j2kstream; } +Byte_t * add_SOTmkr( Byte_t *j2kstream, 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); @@ -265,6 +267,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; @@ -306,6 +309,23 @@ Byte_t * add_mainhead_msgstream( msgqueue_param_t *msgqueue, Byte_t *origstream, return j2kstream; } +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 * add_padding( Byte8_t padding, Byte_t *j2kstream, Byte8_t *j2klen); Byte_t * recons_RPCLbitstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte_t *j2kstream, Byte8_t csn, 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( !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; + if( layers < 0) + layers = numOflayers; + + binOffset = 0; + for( layer_id = 0; layer_id < layers; layer_id++){ - enqueue_message( msg, msgqueue); - cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id] = true; + 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]){ + + 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*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_server/opj_server.c b/applications/jpip/opj_server/opj_server.c index a9778cd4..551eda7a 100644 --- a/applications/jpip/opj_server/opj_server.c +++ b/applications/jpip/opj_server/opj_server.c @@ -407,20 +407,27 @@ bool gene_JPIPstream( query_param_t query_param, *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"); - - codeidx = target->codeidx; + + 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) + 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) + if( !cachemodel->mhead_model && query_param.len != 0) enqueue_mainheader( *msgqueue); enqueue_imagedata( query_param, *msgqueue); } @@ -439,10 +446,11 @@ bool gene_JPIPstream( query_param_t query_param, * @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, msgqueue_param_t *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); /** * enqueue all precincts inside a tile into the queue @@ -451,10 +459,11 @@ void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int * @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, msgqueue_param_t *msgqueue); +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) { @@ -477,6 +486,9 @@ void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue) 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; uSIZ.YTnum; u++){ tile_Yrange = get_tile_Yrange( codeidx->SIZ, tile_id, imgreg.level); @@ -500,7 +512,7 @@ void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue) //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); + enqueue_allprecincts( tile_id, imgreg.level, query_param.lastcomp, query_param.comps, query_param.layers, msgqueue); } else enqueue_tile( tile_id, imgreg.level, msgqueue); @@ -516,7 +528,7 @@ void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *msgqueue) 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); + 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); @@ -527,7 +539,7 @@ void enqueue_imagedata( query_param_t query_param, msgqueue_param_t *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) +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; @@ -567,12 +579,12 @@ void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int 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); + 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, msgqueue); + enqueue_precinct( seq_id, tile_id, c, (dec_lev>level)?-1:layers, msgqueue); } } } @@ -580,7 +592,7 @@ void enqueue_precincts( int xmin, int xmax, int ymin, int ymax, int tile_id, int } } -void enqueue_allprecincts( int tile_id, int level, int lastcomp, bool *comps, msgqueue_param_t *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; @@ -602,7 +614,7 @@ void enqueue_allprecincts( int tile_id, int level, int lastcomp, bool *comps, ms YPsiz = ( codeidx->COD.Scod & 0x01) ? codeidx->COD.YPsiz[ res_lev] : YTsiz; for( i=0; ilevel)?-1:layers, msgqueue); } } } diff --git a/applications/jpip/opj_server/query_parser.c b/applications/jpip/opj_server/query_parser.c index 1195dcc5..f09a6e5e 100644 --- a/applications/jpip/opj_server/query_parser.c +++ b/applications/jpip/opj_server/query_parser.c @@ -116,6 +116,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 +140,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 +151,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 +178,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 +216,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 +243,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;