diff --git a/applications/jpip/CHANGES b/applications/jpip/CHANGES index e57899f7..89252fa1 100644 --- a/applications/jpip/CHANGES +++ b/applications/jpip/CHANGES @@ -5,6 +5,9 @@ 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 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 +#include +#include +#include +#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 #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 #include -#include -#include +#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 -#include -#include -#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); + while(( connected_socket = accept_socket( listening_socket)) != -1 ) + if(!(handle_clientmsg( 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) - 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 new file mode 100644 index 00000000..a17ca3b6 Binary files /dev/null and b/applications/jpip/opj_client/opj_viewer/dist/opj_viewer-20111018.jar differ 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/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 +#include +#include +#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; uSIZ.YTnum; u++){ + tile_Yrange = get_tile_Yrange( codeidx->SIZ, tile_id, imgreg.level); + + for( v=0; vSIZ.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; cSIZ.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 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; cSIZ.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; ilevel)?-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 #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,493 +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); - } - - 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; uSIZ.YTnum; u++){ - tile_Yrange = get_tile_Yrange( codeidx->SIZ, tile_id, imgreg.level); - - for( v=0; vSIZ.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; cSIZ.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 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; cSIZ.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; ilevel)?-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