diff options
| author | Mathieu Malaterre <mathieu.malaterre@gmail.com> | 2012-09-28 08:11:41 +0000 |
|---|---|---|
| committer | Mathieu Malaterre <mathieu.malaterre@gmail.com> | 2012-09-28 08:11:41 +0000 |
| commit | d518970039a19a2a9b6d2bdd592cc88a43897bbb (patch) | |
| tree | 57bac2cf7e63e9352228231062763baac627563c /src/lib/openjpip | |
| parent | 8363a6ab1e031bb4b2e40a92e56efd40fdab1aa1 (diff) | |
[trunk] Start FolderReorgProposal task
Update issue 177
Diffstat (limited to 'src/lib/openjpip')
63 files changed, 12305 insertions, 0 deletions
diff --git a/src/lib/openjpip/CMakeLists.txt b/src/lib/openjpip/CMakeLists.txt new file mode 100644 index 00000000..e42e95fc --- /dev/null +++ b/src/lib/openjpip/CMakeLists.txt @@ -0,0 +1,72 @@ +include_regular_expression("^.*$") + +include_directories( + ${OPENJPEG_SOURCE_DIR}/src/lib/openjp2 + ${FCGI_INCLUDE_DIRS} + ${CURL_INCLUDE_DIRS} +) + +# Defines the source code for the library +set(OPENJPIP_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/boxheader_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/codestream_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/imgreg_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/marker_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/msgqueue_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/box_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/faixbox_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/index_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/metadata_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/placeholder_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/byte_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/ihdrbox_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/manfbox_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/mhixbox_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/target_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/cachemodel_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/j2kheader_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/jp2k_encoder.c + ${CMAKE_CURRENT_SOURCE_DIR}/openjpip.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 + ${CMAKE_CURRENT_SOURCE_DIR}/sock_manager.c + ) + +set(SERVER_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/auxtrans_manager.c + ) + +set(LOCAL_SRCS + ${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}/cache_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/dec_clientmsg_handler.c + ) + +# Build the library +add_library(openjpip_local STATIC ${OPENJPIP_SRCS} ${LOCAL_SRCS}) +target_link_libraries(openjpip_local ${OPENJPEG_LIBRARY_NAME}) +if(WIN32) + # add Winsock on windows+mingw + target_link_libraries(openjpip_local ws2_32) +endif() + +# Install library +install(TARGETS openjpip_local + EXPORT OpenJPEGTargets + DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} COMPONENT Libraries + ) + +if(BUILD_JPIP_SERVER) + add_library(openjpip_server STATIC ${OPENJPIP_SRCS} ${SERVER_SRCS}) + target_link_libraries(openjpip_server ${FCGI_LIBRARIES} ${CURL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) + set_target_properties(openjpip_server + PROPERTIES COMPILE_FLAGS "-DSERVER") + install(TARGETS openjpip_server + EXPORT OpenJPEGTargets + DESTINATION ${OPENJPEG_INSTALL_LIB_DIR} COMPONENT Libraries + ) +endif() diff --git a/src/lib/openjpip/Makefile.am b/src/lib/openjpip/Makefile.am new file mode 100644 index 00000000..6def5d6f --- /dev/null +++ b/src/lib/openjpip/Makefile.am @@ -0,0 +1,153 @@ +MAINTAINERCLEANFILES = Makefile.in + +includesdir = $(includedir)/openjpeg-$(MAJOR_NR).$(MINOR_NR) +includes_HEADERS = + +lib_LTLIBRARIES = + +if WANT_JPIP +lib_LTLIBRARIES += libopenjpip_local.la +endif + +if WANT_JPIP_SERVER +lib_LTLIBRARIES += libopenjpip_server.la +endif + +JPIP_SRC = \ +openjpip.c \ +query_parser.c \ +channel_manager.c \ +session_manager.c \ +jpip_parser.c \ +boxheader_manager.c \ +codestream_manager.c \ +imgreg_manager.c \ +marker_manager.c \ +msgqueue_manager.c \ +box_manager.c \ +faixbox_manager.c \ +index_manager.c \ +metadata_manager.c \ +placeholder_manager.c \ +byte_manager.c \ +ihdrbox_manager.c \ +manfbox_manager.c \ +mhixbox_manager.c \ +target_manager.c \ +cachemodel_manager.c \ +j2kheader_manager.c \ +jp2k_encoder.c \ +sock_manager.c \ +openjpip.h \ +bool.h \ +boxheader_manager.h \ +box_manager.h \ +byte_manager.h \ +codestream_manager.h \ +faixbox_manager.h \ +ihdrbox_manager.h \ +imgreg_manager.h \ +index_manager.h \ +manfbox_manager.h \ +marker_manager.h \ +metadata_manager.h \ +mhixbox_manager.h \ +msgqueue_manager.h \ +placeholder_manager.h \ +target_manager.h \ +cachemodel_manager.h \ +j2kheader_manager.h \ +jp2k_encoder.h \ +query_parser.h \ +channel_manager.h \ +session_manager.h \ +jpip_parser.h \ +jp2k_decoder.h \ +sock_manager.h + +SERVER_SRC = auxtrans_manager.c \ +auxtrans_manager.h + +LOCAL_SRC = jp2k_decoder.c \ +imgsock_manager.c \ +jpipstream_manager.c \ +cache_manager.c \ +dec_clientmsg_handler.c \ +imgsock_manager.h \ +jpipstream_manager.h \ +cache_manager.h \ +dec_clientmsg_handler.h + +libopenjpip_server_la_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/libopenjpeg \ +-I$(top_builddir)/libopenjpeg \ +-I$(top_srcdir)/applications/jpip/libopenjpip \ +-I$(top_builddir)/applications/jpip/libopenjpip \ +@FCGI_CFLAGS@ \ +@LIBCURL_CFLAGS@ \ +-DSERVER +libopenjpip_server_la_CFLAGS = @THREAD_CFLAGS@ +libopenjpip_server_la_LIBADD = @FCGI_LIBS@ @LIBCURL_LIBS@ @THREAD_LIBS@ -lm +libopenjpip_server_la_LDFLAGS = -no-undefined -version-info @lt_version@ +libopenjpip_server_la_SOURCES = $(JPIP_SRC) $(SERVER_SRC) + +libopenjpip_local_la_CPPFLAGS = \ +-I. \ +-I$(top_srcdir)/libopenjpeg \ +-I$(top_builddir)/libopenjpeg \ +-I$(top_srcdir)/applications/jpip/libopenjpip \ +-I$(top_builddir)/applications/jpip/libopenjpip \ +@LIBCURL_CFLAGS@ +libopenjpip_local_la_CFLAGS = +libopenjpip_local_la_LIBADD = $(top_builddir)/libopenjpeg/libopenjpeg.la -lm +libopenjpip_local_la_LDFLAGS = -no-undefined -version-info @lt_version@ +libopenjpip_local_la_SOURCES = $(JPIP_SRC) $(LOCAL_SRC) + +install-data-hook: +if WANT_JPIP_SERVER + @echo -e " (LA)\t$(libdir)/libopenjpip_server.la" >> $(top_builddir)/report.txt +if BUILD_SHARED + @( $(call solist_s) ) >> $(top_builddir)/report.txt +endif +if BUILD_STATIC + @echo -e " (A)\t$(base_s)/$(a_s)" >> $(top_builddir)/report.txt +endif +endif +if WANT_JPIP + @echo -e " (LA)\t$(libdir)/libopenjpip_local.la" >> $(top_builddir)/report.txt +if BUILD_SHARED + @( $(call solist_c) ) >> $(top_builddir)/report.txt +endif +if BUILD_STATIC + @echo -e " (A)\t$(base_c)/$(a_c)" >> $(top_builddir)/report.txt +endif +endif + +solist_s = $(foreach f, $(dll_s) $(so_s), echo -e ' $(SO_PREFIX)\t$(base_s)/$(f)' ;) +get_tok_s = $(shell grep -E "^$(1)=" libopenjpip_server.la | cut -d "'" -f 2) +base_s = $(call get_tok_s,libdir) +so_s = $(call get_tok_s,library_names) +a_s = $(call get_tok_s,old_library) + +solist_c = $(foreach f, $(dll_c) $(so_c), echo -e ' $(SO_PREFIX)\t$(base_c)/$(f)' ;) +get_tok_c = $(shell grep -E "^$(1)=" libopenjpip_local.la | cut -d "'" -f 2) +base_c = $(call get_tok_c,libdir) +so_c = $(call get_tok_c,library_names) +a_c = $(call get_tok_c,old_library) + +if HAVE_WIN32 +SO_PREFIX = (DLL) +dll_s = $(call get_tok_s,dlname) +dll_c = $(call get_tok_c,dlname) +else +if HAVE_DARWIN +SO_PREFIX = (DY) +dll_s = +dll_c = +else +SO_PREFIX = (SO) +dll_s = +dll_c = +endif +endif diff --git a/src/lib/openjpip/auxtrans_manager.c b/src/lib/openjpip/auxtrans_manager.c new file mode 100644 index 00000000..91c06ac4 --- /dev/null +++ b/src/lib/openjpip/auxtrans_manager.c @@ -0,0 +1,267 @@ +/* + * $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 <string.h> +#include <stdlib.h> +#include "auxtrans_manager.h" + +#ifdef _WIN32 +#include <process.h> +#else +#include <pthread.h> +#endif + +#ifdef SERVER +#include "fcgi_stdio.h" +#define logstream FCGI_stdout +#else +#define FCGI_stdout stdout +#define FCGI_stderr stderr +#define logstream stderr +#endif /*SERVER */ + +auxtrans_param_t init_aux_transport( int tcp_auxport, int udp_auxport) +{ + auxtrans_param_t auxtrans; + + auxtrans.tcpauxport = tcp_auxport; + auxtrans.udpauxport = udp_auxport; + + if( 49152 <= tcp_auxport && tcp_auxport <= 65535) + auxtrans.tcplistensock = open_listeningsocket( (uint16_t)tcp_auxport); + else + auxtrans.tcplistensock = -1; + + auxtrans.udplistensock = -1; + /* open listening socket for udp later */ + + return auxtrans; +} + +void close_aux_transport( auxtrans_param_t auxtrans) +{ + if( auxtrans.tcplistensock != -1) + if( close_socket( auxtrans.tcplistensock) != 0) + perror("close"); + + if( auxtrans.udplistensock != -1) + if( close_socket( auxtrans.udplistensock) != 0) + perror("close"); +} + + +/*!< auxiliary response parameters */ +typedef struct aux_response_param{ + char *cid; /*!< channel ID */ + unsigned char *data; /*!< sending data */ + OPJ_SIZE_T datalen; /*!< length of data */ + OPJ_SIZE_T maxlenPerFrame; /*!< maximum data length to send per frame */ + SOCKET listensock; /*!< listeing socket */ +#ifdef _WIN32 + HANDLE hTh; /*!< thread handle */ +#endif +} aux_response_param_t; + +aux_response_param_t * gene_auxresponse( bool istcp, auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T datalen, OPJ_SIZE_T maxlenPerFrame); + +void delete_auxresponse( aux_response_param_t **auxresponse); + + +#ifdef _WIN32 +unsigned __stdcall aux_streaming( void *arg); +#else +void * aux_streaming( void *arg); +#endif + +void send_responsedata_on_aux( bool istcp, auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T datalen, OPJ_SIZE_T maxlenPerFrame) +{ + aux_response_param_t *auxresponse; +#ifdef _WIN32 + unsigned int threadId; +#else + pthread_t thread; + int status; +#endif + + if( istcp){ + if( auxtrans.tcplistensock == -1){ + fprintf( FCGI_stderr, "Error: error in send_responsedata_on_aux(), tcp listening socket no open\n"); + return; + } + + auxresponse = gene_auxresponse( istcp, auxtrans, cid, data, datalen, maxlenPerFrame); + +#ifdef _WIN32 + auxresponse->hTh = (HANDLE)_beginthreadex( NULL, 0, &aux_streaming, auxresponse, 0, &threadId); + if( auxresponse->hTh == 0) + fprintf( FCGI_stderr,"ERRO: pthread_create() %s", strerror( (int)auxresponse->hTh)); +#else + status = pthread_create( &thread, NULL, &aux_streaming, auxresponse); + if( status != 0) + fprintf( FCGI_stderr,"ERROR: pthread_create() %s",strerror(status)); +#endif + } + else + fprintf( FCGI_stderr, "Error: error in send_responsedata_on_aux(), udp not implemented\n"); +} + +aux_response_param_t * gene_auxresponse( bool istcp, auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T datalen, OPJ_SIZE_T maxlenPerFrame) +{ + aux_response_param_t *auxresponse; + + auxresponse = (aux_response_param_t *)malloc( sizeof(aux_response_param_t)); + + auxresponse->cid = strdup( cid); + auxresponse->data = data; + auxresponse->datalen = datalen; + auxresponse->maxlenPerFrame = maxlenPerFrame; + auxresponse->listensock = istcp ? auxtrans.tcplistensock : auxtrans.udplistensock; + + return auxresponse; +} + +void delete_auxresponse( aux_response_param_t **auxresponse) +{ + free( (*auxresponse)->cid); + free( (*auxresponse)->data); + free( *auxresponse); +} + +/** + * Identify cid sent from client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] refcid refenrece channel ID + * @param [in] fp file pointer for log of aux stream + * @return true if identified, false otherwise + */ +bool identify_cid( SOCKET connected_socket, char refcid[], FILE *fp); + +bool recv_ack( SOCKET connected_socket, void *data); + +#ifdef _WIN32 +unsigned __stdcall aux_streaming( void *arg) +#else +void * aux_streaming( void *arg) +#endif +{ + SOCKET connected_socket; + unsigned char *chunk, *ptr; + OPJ_SIZE_T maxLenOfBody, remlen, chunklen; + const OPJ_SIZE_T headlen = 8; + + aux_response_param_t *auxresponse = (aux_response_param_t *)arg; + +#ifdef _WIN32 + CloseHandle( auxresponse->hTh); +#else + pthread_detach( pthread_self()); +#endif + + chunk = (unsigned char *)malloc( auxresponse->maxlenPerFrame); + maxLenOfBody = auxresponse->maxlenPerFrame - headlen; + remlen = auxresponse->datalen; + + while((connected_socket = accept_socket( auxresponse->listensock)) != -1){ + if( identify_cid( connected_socket, auxresponse->cid, FCGI_stderr)){ + ptr = auxresponse->data; + while( 0 < remlen){ + memset( chunk, 0, auxresponse->maxlenPerFrame); + + chunklen = remlen<maxLenOfBody?remlen:maxLenOfBody; + chunklen += headlen; + + chunk[0] = (chunklen >> 8) & 0xff; + chunk[1] = chunklen & 0xff; + + memcpy( chunk+headlen, ptr, chunklen-headlen); + + do{ + send_stream( connected_socket, chunk, chunklen); + }while( !recv_ack( connected_socket, chunk)); + + remlen -= maxLenOfBody; + ptr += maxLenOfBody; + } + if( close_socket( connected_socket) != 0) + perror("close"); + break; + } + } + free( chunk); + + delete_auxresponse( &auxresponse); + +#ifdef _WIN32 + _endthreadex(0); +#else + pthread_exit(0); +#endif + + return 0; +} + + +bool identify_cid( SOCKET connected_socket, char refcid[], FILE *fp) +{ + char *cid; + bool succeed; + + if(!(cid = receive_string( connected_socket))){ + fprintf( fp, "Error: error in identify_cid(), while receiving cid from client\n"); + return false; + } + + succeed = false; + if( strncmp( refcid, cid, strlen( refcid)) == 0) + succeed = true; + + free( cid); + + return succeed; +} + +bool recv_ack( SOCKET connected_socket, void *data) +{ + char *header; + bool succeed; + + header = receive_stream( connected_socket, 8); + + if( memcmp( header, data, 8) != 0) + succeed = false; + else + succeed = true; + + free( header); + + return succeed; +} diff --git a/src/lib/openjpip/auxtrans_manager.h b/src/lib/openjpip/auxtrans_manager.h new file mode 100644 index 00000000..c80988a9 --- /dev/null +++ b/src/lib/openjpip/auxtrans_manager.h @@ -0,0 +1,72 @@ +/* + * $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. + */ + +#ifndef AUXTRANS_MANAGER_H_ +# define AUXTRANS_MANAGER_H_ + +#include "sock_manager.h" + +/** auxiliary transport setting parameters*/ +typedef struct auxtrans_param{ + int tcpauxport; /**< tcp port*/ + int udpauxport; /**< udp port*/ + SOCKET tcplistensock; /**< listenning socket for aux tcp (-1 if not open)*/ + SOCKET udplistensock; /**< listenning socket for aux udp (-1 if not open)*/ +} auxtrans_param_t; + +/** + * Initialize auxiliary transport server of JPIP server + * + * @param[in] tcp_auxport opening tcp auxiliary port ( 0 not to open, valid No. 49152-65535) + * @param[in] udp_auxport opening udp auxiliary port ( 0 not to open, valid No. 49152-65535) + * @return intialized transport parameters + */ +auxtrans_param_t init_aux_transport( int tcp_auxport, int udp_auxport); + +/** + * Close auxiliary transport server of JPIP server + * + * @param[in] auxtrans closing transport server + */ +void close_aux_transport( auxtrans_param_t auxtrans); + +/** + * Send response data on aux transport + * + * @param[in] istcp true if tcp, false if udp + * @param[in] auxtrans available transport parameters + * @param[in] cid channel ID + * @param[in] data sending data + * @param[in] length length of data + * @param[in] maxlenPerFrame maximum data length to send per frame + */ +void send_responsedata_on_aux( bool istcp, auxtrans_param_t auxtrans, const char cid[], void *data, OPJ_SIZE_T length, OPJ_SIZE_T maxlenPerFrame); + +#endif /* !AUXTRANS_MANAGER_H_ */ diff --git a/src/lib/openjpip/bool.h b/src/lib/openjpip/bool.h new file mode 100644 index 00000000..c3adf580 --- /dev/null +++ b/src/lib/openjpip/bool.h @@ -0,0 +1,52 @@ +/* + * $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. + */ + +#ifndef BOOL_H_ +# define BOOL_H_ + +#ifndef false +#define false 0 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef true +#define true (!false) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +typedef char bool; + +#endif /* !BOOL_H_ */ diff --git a/src/lib/openjpip/box_manager.c b/src/lib/openjpip/box_manager.c new file mode 100644 index 00000000..87bb7756 --- /dev/null +++ b/src/lib/openjpip/box_manager.c @@ -0,0 +1,434 @@ +/* + * $Id: box_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <assert.h> +#include "box_manager.h" +#include "opj_inttypes.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*/ + +boxlist_param_t * gene_boxlist(void) +{ + boxlist_param_t *boxlist; + + boxlist = (boxlist_param_t *)malloc( sizeof(boxlist_param_t)); + + boxlist->first = NULL; + boxlist->last = NULL; + + return boxlist; +} + +boxlist_param_t * get_boxstructure( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length) +{ + boxlist_param_t *boxlist; + box_param_t *box; + OPJ_OFF_T pos; + + boxlist = NULL; + pos = offset; + assert( (OPJ_OFF_T)length>=0); + do{ + if(!(box = gene_boxbyOffset( fd, pos))) + break; + + assert( (OPJ_OFF_T)box->length >= 0); + pos += (OPJ_OFF_T)box->length; + + if( !boxlist) + boxlist = gene_boxlist(); + insert_box_into_list( box, boxlist); + }while( pos < offset+(OPJ_OFF_T)length); + + return boxlist; +} + +box_param_t * gene_boxbyOffset( int fd, OPJ_OFF_T offset) +{ + Byte_t *data; + Byte8_t boxlen; + Byte_t headlen; + char *boxtype; + box_param_t *box; + + /* read LBox and TBox*/ + if(!(data = fetch_bytes( fd, offset, 8))){ + fprintf( FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %" PRId64 ")\n", fd, offset); + return NULL; + } + + headlen = 8; + boxlen = (Byte8_t)big4(data); + boxtype = (char *)(data+4); + + /* box type constraint*/ + if( !isalpha(boxtype[0]) || !isalpha(boxtype[1]) || + (!isalnum(boxtype[2])&&!isspace(boxtype[2])) || + (!isalpha(boxtype[3])&&!isspace(boxtype[3]))){ + free( data); + return NULL; + } + + if( boxlen == 1){ + Byte_t *data2; + headlen = 16; + /* read XLBox*/ + if((data2 = fetch_bytes( fd, offset+8, 8))){ + boxlen = big8(data2); + free(data2); + } + else{ + fprintf( FCGI_stderr, "Error: error in gene_boxbyOffset( %d, %" PRId64 ")\n", fd, offset); + free( data); + return NULL; + } + } + box = (box_param_t *)malloc( sizeof( box_param_t)); + box->fd = fd; + box->offset = offset; + box->headlen = headlen; + box->length = boxlen; + strncpy( box->type, boxtype, 4); + box->next = NULL; + free( data); + return box; +} + +box_param_t * gene_boxbyOffinStream( Byte_t *stream, OPJ_OFF_T offset) +{ + Byte8_t boxlen; + Byte_t headlen; + char *boxtype; + box_param_t *box; + + /* read LBox and TBox*/ + headlen = 8; + boxlen = (Byte8_t)big4( stream); + boxtype = (char *)( stream+4); + + /* box type constraint*/ + if( !isalpha(boxtype[0]) || !isalpha(boxtype[1]) || + (!isalnum(boxtype[2])&&!isspace(boxtype[2])) || + (!isalpha(boxtype[3])&&!isspace(boxtype[3]))){ + return NULL; + } + + if( boxlen == 1){ + headlen = 16; + boxlen = big8( stream+8); /* read XLBox*/ + } + box = (box_param_t *)malloc( sizeof( box_param_t)); + box->fd = -1; + box->offset = offset; + box->headlen = headlen; + box->length = boxlen; + strncpy( box->type, boxtype, 4); + box->next = NULL; + + return box; +} + + +box_param_t * gene_boxbyType( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length, const char TBox[]) +{ + OPJ_OFF_T pos; + Byte_t *data; + Byte8_t boxlen; + Byte_t headlen; + char *boxtype; + box_param_t *foundbox; + + + if( length==0){ /* set the max length*/ + if( get_filesize( fd) <= offset ) + return NULL; + assert( get_filesize( fd) > offset ); + assert( offset >= 0 ); + length = (OPJ_SIZE_T)(get_filesize( fd) - offset); + } + + pos = offset; + assert( pos >= 0 ); + assert( (OPJ_OFF_T)length >= 0 ); + while( pos < offset+(OPJ_OFF_T)length-7){ /* LBox+TBox-1=7*/ + + /* read LBox and TBox*/ + if((data = fetch_bytes( fd, pos, 8))){ + headlen = 8; + boxlen = (Byte8_t)big4(data); + boxtype = (char *)(data+4); + + if( boxlen == 1){ + Byte_t *data2; + headlen = 16; + /* read XLBox*/ + if((data2 = fetch_bytes( fd, pos+8, 8))){ + boxlen = big8(data2); + free(data2); + } + else{ + fprintf( FCGI_stderr, "Error: error in gene_boxbyType( %d, %" PRId64 ", %" PRId64 ", %s)\n", fd, offset, length, TBox); + return NULL; + } + } + if( strncmp ( boxtype, TBox, 4) == 0){ + foundbox = (box_param_t *)malloc( sizeof( box_param_t)); + foundbox->fd = fd; + foundbox->offset = pos; + foundbox->headlen = headlen; + foundbox->length = boxlen; + strncpy( foundbox->type, TBox, 4); + foundbox->next = NULL; + free( data); + return foundbox; + } + free( data); + } + else{ + fprintf( FCGI_stderr, "Error: error in gene_boxbyType( %d, %" PRId64 ", %" PRId64 ", %s)\n", fd, offset, length, TBox); + return NULL; + } + assert( ((Byte8_t)pos+boxlen)>=(Byte8_t)pos); + pos+= (OPJ_OFF_T)boxlen; + } + fprintf( FCGI_stderr, "Error: Box %s not found\n", TBox); + + return NULL; +} + +box_param_t * gene_boxbyTypeinStream( Byte_t *stream, OPJ_OFF_T offset, OPJ_SIZE_T length, const char TBox[]) +{ + OPJ_OFF_T pos; + Byte_t *data; + Byte8_t boxlen; + Byte_t headlen; + char *boxtype; + box_param_t *foundbox; + + pos = offset; + assert( pos >= 0 ); + assert( (OPJ_OFF_T)length >= 0 ); + while( pos < offset+(OPJ_OFF_T)(length)-7){ /* LBox+TBox-1=7*/ + + /* read LBox and TBox*/ + data = stream + pos; + headlen = 8; + boxlen = (Byte8_t)big4(data); + boxtype = (char *)(data+4); + + if( boxlen == 1){ + /* read XLBox*/ + headlen = 16; + boxlen = big8( data+8); + } + + if( strncmp ( boxtype, TBox, 4) == 0){ + foundbox = (box_param_t *)malloc( sizeof( box_param_t)); + foundbox->fd = -1; + foundbox->offset = pos; + foundbox->headlen = headlen; + foundbox->length = boxlen; + strncpy( foundbox->type, TBox, 4); + foundbox->next = NULL; + return foundbox; + } + assert( ((Byte8_t)pos+boxlen)>=(Byte8_t)pos); + pos+= (OPJ_OFF_T)boxlen; + } + fprintf( FCGI_stderr, "Error: Box %s not found\n", TBox); + + return NULL; +} + +box_param_t * gene_childboxbyOffset( box_param_t *superbox, OPJ_OFF_T offset) +{ + return gene_boxbyOffset( superbox->fd, get_DBoxoff( superbox)+offset); +} + +box_param_t * gene_childboxbyType( box_param_t *superbox, OPJ_OFF_T offset, const char TBox[]) +{ + OPJ_SIZE_T DBOXlen = get_DBoxlen(superbox); + assert( offset >= 0 ); + if( DBOXlen < (OPJ_SIZE_T)offset ) + { + fprintf( FCGI_stderr, "Error: Impossible happen %lu < %ld\n", DBOXlen, offset); + return NULL; + } + return gene_boxbyType( superbox->fd, get_DBoxoff( superbox)+offset, DBOXlen-(OPJ_SIZE_T)offset, TBox); +} + +OPJ_OFF_T get_DBoxoff( box_param_t *box) +{ + return box->offset+box->headlen; +} + +OPJ_SIZE_T get_DBoxlen( box_param_t *box) +{ + return box->length - box->headlen; +} + +Byte_t * fetch_headbytes( box_param_t *box) +{ + return fetch_bytes( box->fd, box->offset, box->headlen); +} + +Byte_t * fetch_DBoxbytes( box_param_t *box, OPJ_OFF_T offset, OPJ_SIZE_T size) +{ + return fetch_bytes( box->fd, get_DBoxoff( box)+offset, size); +} + +Byte_t fetch_DBox1byte( box_param_t *box, OPJ_OFF_T offset) +{ + return fetch_1byte( box->fd, get_DBoxoff( box)+offset); +} + +Byte2_t fetch_DBox2bytebigendian( box_param_t *box, OPJ_OFF_T offset) +{ + return fetch_2bytebigendian( box->fd, get_DBoxoff( box)+offset); +} + +Byte4_t fetch_DBox4bytebigendian( box_param_t *box, OPJ_OFF_T offset) +{ + return fetch_4bytebigendian( box->fd, get_DBoxoff( box)+offset); +} + +Byte8_t fetch_DBox8bytebigendian( box_param_t *box, OPJ_OFF_T offset) +{ + return fetch_8bytebigendian( box->fd, get_DBoxoff( box)+offset); +} + +box_param_t * search_box( const char type[], boxlist_param_t *boxlist) +{ + box_param_t *foundbox; + + foundbox = boxlist->first; + + while( foundbox != NULL){ + + if( strncmp( type, foundbox->type, 4) == 0) + return foundbox; + + foundbox = foundbox->next; + } + fprintf( FCGI_stderr, "Error: Box %s not found\n", type); + + return NULL; +} + +void print_box( box_param_t *box) +{ + fprintf( logstream, "box info:\n" + "\t type: %.4s\n" + "\t offset: %" PRId64 " %#" PRIx64 "\n" + "\t header length: %d\n" + "\t length: %" PRId64 " %#" PRIx64 "\n", box->type, box->offset, + box->offset, box->headlen, box->length, box->length); +} + +void print_allbox( boxlist_param_t *boxlist) +{ + box_param_t *ptr; + + if( !boxlist) + return; + + ptr = boxlist->first; + if( !ptr) + fprintf( logstream, "no box\n"); + + fprintf( logstream, "all box info: \n"); + while( ptr != NULL){ + print_box( ptr); + ptr=ptr->next; + } +} + +void delete_box_in_list( box_param_t **box, boxlist_param_t *boxlist) +{ + box_param_t *ptr; + + if( *box == boxlist->first) + boxlist->first = (*box)->next; + else{ + ptr = boxlist->first; + while( ptr->next != *box){ + ptr=ptr->next; + } + ptr->next = (*box)->next; + + if( *box == boxlist->last) + boxlist->last = ptr; + } + free( *box); +} + +void delete_box_in_list_by_type( const char type[], boxlist_param_t *boxlist) +{ + box_param_t *box; + + box = search_box( type, boxlist); + delete_box_in_list( &box, boxlist); +} + +void delete_boxlist( boxlist_param_t **boxlist) +{ + box_param_t *boxPtr, *boxNext; + + if(!(*boxlist)) + return; + + boxPtr = (*boxlist)->first; + while( boxPtr != NULL){ + boxNext=boxPtr->next; + free( boxPtr); + boxPtr=boxNext; + } + free( *boxlist); +} + +void insert_box_into_list( box_param_t *box, boxlist_param_t *boxlist) +{ + if( boxlist->first) + boxlist->last->next = box; + else + boxlist->first = box; + boxlist->last = box; +} diff --git a/src/lib/openjpip/box_manager.h b/src/lib/openjpip/box_manager.h new file mode 100644 index 00000000..88cd5336 --- /dev/null +++ b/src/lib/openjpip/box_manager.h @@ -0,0 +1,264 @@ +/* + * $Id: box_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef BOX_MANAGER_H_ +# define BOX_MANAGER_H_ + +#include "byte_manager.h" + +/** box parameters*/ +typedef struct box_param{ + int fd; /**< file descriptor*/ + OPJ_OFF_T offset; /**< byte position of the whole Box (LBox) in the file*/ + Byte_t headlen; /**< header length 8 or 16*/ + Byte8_t length; /**< length of the whole Box*/ + char type[4]; /**< type of information in the DBox*/ + struct box_param *next; /**< pointer to the next box*/ +} box_param_t; + + +/** Box list parameters*/ +typedef struct boxlist_param{ + box_param_t *first; /**< first box pointer of the list*/ + box_param_t *last; /**< last box pointer of the list*/ +} boxlist_param_t; + + +/** + * generate a box list + * + * @return pointer to the generated box list + */ +boxlist_param_t * gene_boxlist(void); + +/** + * get box structure of JP2 file + * + * @param[in] fd file descriptor + * @param[in] offset offset of the decomposing region + * @param[in] length length of the decomposing region + * @return pointer to the generated boxlist + */ +boxlist_param_t * get_boxstructure( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length); + + +/** + * generate box from JP2 file at the given offset + * + * @param[in] fd file discriptor of the JP2 file + * @param[in] offset Box offset + * @return pointer to the structure of generate box parameters + */ +box_param_t * gene_boxbyOffset( int fd, OPJ_OFF_T offset); + + +/** + * generate box from code stream (JPP or JPT stream) at the given offset + * + * @param[in] stream code stream of a box + * @param[in] offset Box offset of the whole stream + * @return pointer to the structure of generate box parameters + */ +box_param_t * gene_boxbyOffinStream( Byte_t *stream, OPJ_OFF_T offset); + +/** + * generate(search) box from JP2 file + * + * @param[in] fd file discriptor of the JP2 file + * @param[in] offset start Byte position of the search + * @param[in] length Byte length of the search, if 0, size to the end of file + * @param[in] TBox Box Type + * @return pointer to the structure of generate/found box parameters + */ +box_param_t * gene_boxbyType( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length, const char TBox[]); + +/** + * generate(search) box from code stream + * + * @param[in] stream code stream ( from the first byte) + * @param[in] offset start Byte position of the search + * @param[in] length Byte length of the search, if 0, size to the end of file + * @param[in] TBox Box Type + * @return pointer to the structure of generate/found box parameters + */ +box_param_t * gene_boxbyTypeinStream( Byte_t *stream, OPJ_OFF_T offset, OPJ_SIZE_T length, const char TBox[]); + +/** + * generate child box from JP2 file at the given offset + * + * @param[in] superbox super box pointer + * @param[in] offset offset from DBox first byte of superbox + * @return pointer to the structure of generate box parameters + */ +box_param_t * gene_childboxbyOffset( box_param_t *superbox, OPJ_OFF_T offset); + +/** + * generate(search) box from JP2 file + * + * @param[in] superbox super box pointer + * @param[in] offset offset from DBox first byte of superbox + * @param[in] TBox Box Type + * @return pointer to the structure of generate/found box parameters + */ +box_param_t * gene_childboxbyType( box_param_t *superbox, OPJ_OFF_T offset, const char TBox[]); + +/** + * get DBox offset + * + * @param[in] box box pointer + * @return DBox offset (byte position) in the file + */ +OPJ_OFF_T get_DBoxoff( box_param_t *box); + + +/** + * get DBox length + * + * @param[in] box box pointer + * @return DBox length ( content length) + */ +OPJ_SIZE_T get_DBoxlen( box_param_t *box); + + +/** + * fetch header bytes in file stream + * + * @param[in] box box pointer + * @return pointer to the fetched bytes + */ +Byte_t * fetch_headbytes( box_param_t *box); + + +/** + * fetch DBox (Box Contents) bytes of data in file stream + * + * @param[in] box box pointer + * @param[in] offset start Byte position in DBox + * @param[in] size Byte length + * @return pointer to the fetched data + */ +Byte_t * fetch_DBoxbytes( box_param_t *box, OPJ_OFF_T offset, OPJ_SIZE_T size); + +/** + * fetch DBox (Box Contents) 1-byte Byte codes in file stream + * + * @param[in] box box pointer + * @param[in] offset start Byte position in DBox + * @return fetched code + */ +Byte_t fetch_DBox1byte( box_param_t *box, OPJ_OFF_T offset); + +/** + * fetch DBox (Box Contents) 2-byte big endian Byte codes in file stream + * + * @param[in] box box pointer + * @param[in] offset start Byte position in DBox + * @return fetched code + */ +Byte2_t fetch_DBox2bytebigendian( box_param_t *box, OPJ_OFF_T offset); + +/** + * fetch DBox (Box Contents) 4-byte big endian Byte codes in file stream + * + * @param[in] box box pointer + * @param[in] offset start Byte position in DBox + * @return fetched code + */ +Byte4_t fetch_DBox4bytebigendian( box_param_t *box, OPJ_OFF_T offset); + +/** + * fetch DBox (Box Contents) 8-byte big endian Byte codes in file stream + * + * @param[in] box box pointer + * @param[in] offset start Byte position in DBox + * @return fetched code + */ +Byte8_t fetch_DBox8bytebigendian( box_param_t *box, OPJ_OFF_T offset); + + +/** + * search a box by box type + * + * @param[in] type box type + * @param[in] boxlist box list pointer + * @return found box pointer + */ +box_param_t * search_box( const char type[], boxlist_param_t *boxlist); + +/** + * print box parameters + * + * @param[in] box box pointer + */ +void print_box( box_param_t *box); + + +/** + * print all box parameters + * + * @param[in] boxlist box list pointer + */ +void print_allbox( boxlist_param_t *boxlist); + +/** + * delete a box in list + * + * @param[in,out] box address of the deleting box pointer + * @param[in] boxlist box list pointer + */ +void delete_box_in_list( box_param_t **box, boxlist_param_t *boxlist); + + +/** + * delete a box in list by Type + * + * @param[in,out] type box type + * @param[in] boxlist box list pointer + */ +void delete_box_in_list_by_type( const char type[], boxlist_param_t *boxlist); + + +/** + * delete box list + * + * @param[in,out] boxlist address of the box list pointer + */ +void delete_boxlist( boxlist_param_t **boxlist); + + +/** + * insert a box into list + * + * @param[in] box box pointer + * @param[in] boxlist box list pointer + */ +void insert_box_into_list( box_param_t *box, boxlist_param_t *boxlist); + +#endif /* !BOX_MANAGER_H_ */ diff --git a/src/lib/openjpip/boxheader_manager.c b/src/lib/openjpip/boxheader_manager.c new file mode 100644 index 00000000..b345a96d --- /dev/null +++ b/src/lib/openjpip/boxheader_manager.c @@ -0,0 +1,84 @@ +/* + * $Id: boxheader_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 <stdlib.h> +#include "boxheader_manager.h" +#include "opj_inttypes.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*/ + + +boxheader_param_t * gene_boxheader( int fd, OPJ_OFF_T offset) +{ + Byte8_t boxlen; + Byte_t headlen; + char *boxtype; + boxheader_param_t *boxheader; + + boxlen = fetch_4bytebigendian( fd, offset); + boxtype = (char *)fetch_bytes( fd, offset+4, 4); + headlen = 8; + + if( boxlen == 1){ /* read XLBox */ + boxlen = fetch_8bytebigendian( fd, offset+8); + headlen = 16; + } + + boxheader = (boxheader_param_t *)malloc( sizeof( boxheader_param_t)); + boxheader->headlen = headlen; + boxheader->length = boxlen; + strncpy( boxheader->type, boxtype, 4); + boxheader->next = NULL; + + free( boxtype); + return boxheader; +} + +boxheader_param_t * gene_childboxheader( box_param_t *superbox, OPJ_OFF_T offset) +{ + return gene_boxheader( superbox->fd, get_DBoxoff(superbox)+offset); +} + +void print_boxheader( boxheader_param_t *boxheader) +{ + fprintf( logstream, "boxheader info:\n" + "\t type: %.4s\n" + "\t length:%" PRId64 " %#" PRIx64 "\n", boxheader->type, boxheader->length, boxheader->length); +} diff --git a/src/lib/openjpip/boxheader_manager.h b/src/lib/openjpip/boxheader_manager.h new file mode 100644 index 00000000..f8e48f39 --- /dev/null +++ b/src/lib/openjpip/boxheader_manager.h @@ -0,0 +1,71 @@ +/* + * $Id: boxheader_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef BOXHEADER_MANAGER_H_ +# define BOXHEADER_MANAGER_H_ + +#include "byte_manager.h" +#include "box_manager.h" + +/** box header parameters*/ +typedef struct boxheader_param{ + Byte_t headlen; /**< header length 8 or 16*/ + Byte8_t length; /**< length of the reference Box*/ + char type[4]; /**< type of information in the DBox*/ + struct boxheader_param *next; /**< pointer to the next header box*/ +} boxheader_param_t; + + +/** + * generate a box header at the given offset + * + * @param[in] fd file discriptor of the JP2 file + * @param[in] offset Box offset + * @return pointer to the structure of generate box header parameters + */ +boxheader_param_t * gene_boxheader( int fd, OPJ_OFF_T offset); + +/** + * generate a child box header at the given offset + * + * @param[in] superbox super box pointer + * @param[in] offset offset from DBox first byte of superbox + * @return pointer to the structure of generate box header parameters + */ +boxheader_param_t * gene_childboxheader( box_param_t *superbox, OPJ_OFF_T offset); + +/** + * print box header parameters + * + * @param[in] boxheader boxheader pointer + */ +void print_boxheader( boxheader_param_t *boxheader); + +#endif /* !BOXHEADER_MANAGER_H_ */ diff --git a/src/lib/openjpip/byte_manager.c b/src/lib/openjpip/byte_manager.c new file mode 100644 index 00000000..502c26bd --- /dev/null +++ b/src/lib/openjpip/byte_manager.c @@ -0,0 +1,172 @@ +/* + * $Id: byte_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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> +#ifdef _WIN32 +#include <io.h> +#else +#include <sys/types.h> +#include <unistd.h> +#endif +#include <stdlib.h> +#include <sys/stat.h> +#include "byte_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*/ + + +Byte_t * fetch_bytes( int fd, OPJ_OFF_T offset, OPJ_SIZE_T size) +{ + Byte_t *data; + + if( lseek( fd, offset, SEEK_SET)==-1){ + fprintf( FCGI_stdout, "Reason: Target broken (fseek error)\r\n"); + fprintf( FCGI_stderr, "Error: error in fetch_bytes( %d, %ld, %lu)\n", fd, offset, size); + return NULL; + } + + data = (Byte_t *)malloc( size); + + if( (OPJ_SIZE_T)read( fd, data, size) != size){ + free( data); + fprintf( FCGI_stdout, "Reason: Target broken (read error)\r\n"); + fprintf( FCGI_stderr, "Error: error in fetch_bytes( %d, %ld, %lu)\n", fd, offset, size); + return NULL; + } + return data; +} + +Byte_t fetch_1byte( int fd, OPJ_OFF_T offset) +{ + Byte_t code; + + if( lseek( fd, offset, SEEK_SET)==-1){ + fprintf( FCGI_stdout, "Reason: Target broken (seek error)\r\n"); + fprintf( FCGI_stderr, "Error: error in fetch_1byte( %d, %ld)\n", fd, offset); + return 0; + } + + if( read( fd, &code, 1) != 1){ + fprintf( FCGI_stdout, "Reason: Target broken (read error)\r\n"); + fprintf( FCGI_stderr, "Error: error in fetch_bytes( %d, %ld)\n", fd, offset); + return 0; + } + return code; +} + +Byte2_t fetch_2bytebigendian( int fd, OPJ_OFF_T offset) +{ + Byte_t *data; + Byte2_t code; + + if(!(data = fetch_bytes( fd, offset, 2))){ + fprintf( FCGI_stderr, "Error: error in fetch_2bytebigendian( %d, %ld)\n", fd, offset); + return 0; + } + code = big2(data); + free( data); + + return code; +} + +Byte4_t fetch_4bytebigendian( int fd, OPJ_OFF_T offset) +{ + Byte_t *data; + Byte4_t code; + + if(!(data = fetch_bytes( fd, offset, 4))){ + fprintf( FCGI_stderr, "Error: error in fetch_4bytebigendian( %d, %ld)\n", fd, offset); + return 0; + } + code = big4(data); + free( data); + + return code; +} + +Byte8_t fetch_8bytebigendian( int fd, OPJ_OFF_T offset) +{ + Byte_t *data; + Byte8_t code; + + if(!(data = fetch_bytes( fd, offset, 8))){ + fprintf( FCGI_stderr, "Error: error in fetch_8bytebigendian( %d, %ld)\n", fd, offset); + return 0; + } + code = big8(data); + free( data); + + return code; +} + + +Byte2_t big2( Byte_t *buf) +{ + return (Byte2_t)((((Byte2_t) buf[0]) << 8) + ((Byte2_t) buf[1])); +} + +Byte4_t big4( Byte_t *buf) +{ + return (((((((Byte4_t) buf[0]) << 8) + ((Byte4_t) buf[1])) << 8) + + ((Byte4_t) buf[2])) << 8) + ((Byte4_t) buf[3]); +} + +Byte8_t big8( Byte_t *buf) +{ + return (((Byte8_t) big4 (buf)) << 32) + + ((Byte8_t) big4 (buf + 4)); +} + +void modify_4Bytecode( Byte4_t code, Byte_t *stream) +{ + *stream = (Byte_t) ((Byte4_t)(code & 0xff000000) >> 24); + *(stream+1) = (Byte_t) ((Byte4_t)(code & 0x00ff0000) >> 16); + *(stream+2) = (Byte_t) ((Byte4_t)(code & 0x0000ff00) >> 8); + *(stream+3) = (Byte_t) (code & 0x000000ff); +} + +OPJ_OFF_T get_filesize( int fd) +{ + struct stat sb; + + if( fstat( fd, &sb) == -1){ + fprintf( FCGI_stdout, "Reason: Target broken (fstat error)\r\n"); + fprintf( FCGI_stderr, "Error: error in get_filesize( %d)\n", fd); + return 0; + } + return sb.st_size; +} diff --git a/src/lib/openjpip/byte_manager.h b/src/lib/openjpip/byte_manager.h new file mode 100644 index 00000000..0a29503e --- /dev/null +++ b/src/lib/openjpip/byte_manager.h @@ -0,0 +1,129 @@ +/* + * $Id: byte_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef BYTE_MANAGER_H_ +#define BYTE_MANAGER_H_ + +#include <stddef.h> +#include "opj_stdint.h" +typedef uint8_t Byte_t; +typedef uint16_t Byte2_t; +typedef uint32_t Byte4_t; +typedef uint64_t Byte8_t; + +/** + * fetch bytes of data in file stream + * + * @param[in] fd file discriptor + * @param[in] offset start Byte position + * @param[in] size Byte length + * @return pointer to the fetched data + */ +Byte_t * fetch_bytes( int fd, OPJ_OFF_T offset, OPJ_SIZE_T size); + + +/** + * fetch a 1-byte Byte codes in file stream + * + * @param[in] fd file discriptor + * @param[in] offset start Byte position + * @return fetched codes + */ +Byte_t fetch_1byte( int fd, OPJ_OFF_T offset); + +/** + * fetch a 2-byte big endian Byte codes in file stream + * + * @param[in] fd file discriptor + * @param[in] offset start Byte position + * @return fetched codes + */ +Byte2_t fetch_2bytebigendian( int fd, OPJ_OFF_T offset); + +/** + * fetch a 4-byte big endian Byte codes in file stream + * + * @param[in] fd file discriptor + * @param[in] offset start Byte position + * @return fetched codes + */ +Byte4_t fetch_4bytebigendian( int fd, OPJ_OFF_T offset); + +/** + * fetch a 8-byte big endian Byte codes in file stream + * + * @param[in] fd file discriptor + * @param[in] offset start Byte position + * @return fetched codes + */ +Byte8_t fetch_8bytebigendian( int fd, OPJ_OFF_T offset); + + +/** + * convert 2-byte big endian Byte codes to number + * + * @param[in] buf Byte codes + * @return resolved number + */ +Byte2_t big2( Byte_t *buf); + +/** + * convert 4-byte big endian Byte codes to number + * + * @param[in] buf Byte codes + * @return resolved number + */ +Byte4_t big4( Byte_t *buf); + +/** + * convert 8-byte big endian Byte codes to number + * + * @param[in] buf Byte codes + * @return resolved number + */ +Byte8_t big8( Byte_t *buf); + +/** + * modify 4Byte code in a codestream + * + * @param[in] code code value + * @param[out] stream modifying codestream + */ +void modify_4Bytecode( Byte4_t code, Byte_t *stream); + +/** + * Get file size + * + * @param[in] fd file discriptor + * @return file size + */ +OPJ_OFF_T get_filesize( int fd); + +#endif /* !BYTE_MANAGER_H_ */ diff --git a/src/lib/openjpip/cache_manager.c b/src/lib/openjpip/cache_manager.c new file mode 100644 index 00000000..76f7b7b3 --- /dev/null +++ b/src/lib/openjpip/cache_manager.c @@ -0,0 +1,275 @@ +/* + * $Id: cache_manager.c 53 2011-05-09 16:55:39Z kaori $ + * + * 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 "cache_manager.h" + +cachelist_param_t * gene_cachelist(void) +{ + cachelist_param_t *cachelist; + + cachelist = (cachelist_param_t *)malloc( sizeof(cachelist_param_t)); + + cachelist->first = NULL; + cachelist->last = NULL; + + return cachelist; +} + +void delete_cachelist(cachelist_param_t **cachelist) +{ + cache_param_t *cachePtr, *cacheNext; + + cachePtr = (*cachelist)->first; + while( cachePtr != NULL){ + cacheNext=cachePtr->next; + delete_cache( &cachePtr); + cachePtr=cacheNext; + } + free( *cachelist); +} + +cache_param_t * gene_cache( const char *targetname, int csn, char *tid, char *cid) +{ + cache_param_t *cache; + + cache = (cache_param_t *)malloc( sizeof(cache_param_t)); + cache->filename = strdup( targetname); + cache->tid = strdup( tid); + cache->csn = csn; + cache->cid = (char **)malloc( sizeof(char *)); + *cache->cid = strdup( cid); + cache->numOfcid = 1; +#if 1 + cache->metadatalist = NULL; +#else + cache->metadatalist = gene_metadatalist(); +#endif + cache->ihdrbox = NULL; + cache->next = NULL; + + return cache; +} + +void delete_cache( cache_param_t **cache) +{ + int i; + + free( (*cache)->filename); + free( (*cache)->tid); + + delete_metadatalist( &(*cache)->metadatalist); + + if((*cache)->ihdrbox) + free((*cache)->ihdrbox); + for( i=0; i<(*cache)->numOfcid; i++) + free( (*cache)->cid[i]); + free( (*cache)->cid); + free( *cache); +} + +void insert_cache_into_list( cache_param_t *cache, cachelist_param_t *cachelist) +{ + if( cachelist->first) + cachelist->last->next = cache; + else + cachelist->first = cache; + cachelist->last = cache; +} + +cache_param_t * search_cache( const char targetname[], cachelist_param_t *cachelist) +{ + cache_param_t *foundcache; + + if( !targetname) + return NULL; + + foundcache = cachelist->first; + + while( foundcache != NULL){ + + if( strcmp( targetname, foundcache->filename) == 0) + return foundcache; + + foundcache = foundcache->next; + } + return NULL; +} + +cache_param_t * search_cacheBycsn( int csn, cachelist_param_t *cachelist) +{ + cache_param_t *foundcache; + + foundcache = cachelist->first; + + while( foundcache != NULL){ + + if( csn == foundcache->csn) + return foundcache; + foundcache = foundcache->next; + } + return NULL; +} + +cache_param_t * search_cacheBycid( const char cid[], cachelist_param_t *cachelist) +{ + cache_param_t *foundcache; + int i; + + if( !cid) + return NULL; + + foundcache = cachelist->first; + + while( foundcache != NULL){ + for( i=0; i<foundcache->numOfcid; i++) + if( strcmp( cid, foundcache->cid[i]) == 0) + return foundcache; + foundcache = foundcache->next; + } + return NULL; +} + +cache_param_t * search_cacheBytid( const char tid[], cachelist_param_t *cachelist) +{ + cache_param_t *foundcache; + + if( !tid) + return NULL; + + foundcache = cachelist->first; + + while( foundcache != NULL){ + if( strcmp( tid, foundcache->tid) == 0) + return foundcache; + foundcache = foundcache->next; + } + return NULL; +} + +void add_cachecid( const char *cid, cache_param_t *cache) +{ + if( !cid) + return; + + if( (cache->cid = realloc( cache->cid, (OPJ_SIZE_T)(cache->numOfcid+1)*sizeof(char *))) == NULL){ + fprintf( stderr, "failed to add new cid to cache table in add_cachecid()\n"); + return; + } + + cache->cid[ cache->numOfcid] = strdup( cid); + + cache->numOfcid ++; +} + +void update_cachetid( const char *tid, cache_param_t *cache) +{ + if( !tid) + return; + + if( tid[0] != '0' && strcmp( tid, cache->tid) !=0){ + fprintf( stderr, "tid is updated to %s for %s\n", tid, cache->filename); + free( cache->tid); + cache->tid = strdup( tid); + } +} + +void remove_cidInCache( const char *cid, cache_param_t *cache); + +void remove_cachecid( const char *cid, cachelist_param_t *cachelist) +{ + cache_param_t *cache; + + cache = search_cacheBycid( cid, cachelist); + remove_cidInCache( cid, cache); +} + +void remove_cidInCache( const char *cid, cache_param_t *cache) +{ + int idx = -1; + char **tmp; + int i, j; + + for( i=0; i<cache->numOfcid; i++) + if( strcmp( cid, cache->cid[i]) == 0){ + idx = i; + break; + } + + if( idx == -1){ + fprintf( stderr, "cid: %s not found\n", cid); + return; + } + + tmp = cache->cid; + + cache->cid = (char **)malloc( (OPJ_SIZE_T)(cache->numOfcid-1)*sizeof(char *)); + + for( i=0, j=0; i<cache->numOfcid; i++){ + if( i != idx){ + cache->cid[j] = strdup( tmp[i]); + j++; + } + free( tmp[i]); + } + free( tmp); + + cache->numOfcid --; +} + +void print_cache( cache_param_t *cache) +{ + int i; + + fprintf( stdout,"cache\n"); + fprintf( stdout,"\t filename: %s\n", cache->filename); + fprintf( stdout,"\t tid: %s\n", cache->tid); + fprintf( stdout,"\t csn: %d\n", cache->csn); + fprintf( stdout,"\t cid:"); + + for( i=0; i<cache->numOfcid; i++) + fprintf( stdout," %s", cache->cid[i]); + fprintf( stdout,"\n"); +} + +void print_allcache( cachelist_param_t *cachelist) +{ + cache_param_t *ptr; + + fprintf( stdout,"cache list\n"); + + ptr = cachelist->first; + while( ptr != NULL){ + print_cache( ptr); + ptr=ptr->next; + } +} diff --git a/src/lib/openjpip/cache_manager.h b/src/lib/openjpip/cache_manager.h new file mode 100644 index 00000000..0c9afb0b --- /dev/null +++ b/src/lib/openjpip/cache_manager.h @@ -0,0 +1,177 @@ +/* + * $Id: cache_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef CACHE_MANAGER_H_ +# define CACHE_MANAGER_H_ + +#include "metadata_manager.h" +#include "ihdrbox_manager.h" + +/** cache parameters*/ +typedef struct cache_param{ + char *filename; /**< file name*/ + char *tid; /**< taregt identifier*/ + int csn; /**< codestream number*/ + char **cid; /**< dynamic array of channel identifiers*/ + int numOfcid; /**< number of cids*/ + metadatalist_param_t *metadatalist; /**< metadata-bin list*/ + ihdrbox_param_t *ihdrbox; /**< ihdrbox*/ + struct cache_param *next; /**< pointer to the next cache*/ +} cache_param_t; + +/**< cache list parameters*/ +typedef struct cachelist_param{ + cache_param_t *first; /**< first cache pointer of the list*/ + cache_param_t *last; /**< last cache pointer of the list*/ +} cachelist_param_t; + + +/** + * generate a cache list + * + * @return pointer to the generated cache list + */ +cachelist_param_t * gene_cachelist(void); + +/** + * delete cache list + * + * @param[in,out] cachelist address of the cache list pointer + */ +void delete_cachelist(cachelist_param_t **cachelist); + +/** + * generate a cache + * + * @param[in] targetname target file name + * @param[in] csn codestream number + * @param[in] tid target identifier + * @param[in] cid channel identifier + * @return pointer to the generated cache + */ +cache_param_t * gene_cache( const char *targetname, int csn, char *tid, char *cid); + +/** + * delete a cache + * + * @param[in] cache address of the cache pointer + */ +void delete_cache( cache_param_t **cache); + +/** + * insert a cache into list + * + * @param[in] cache cache pointer + * @param[in] cachelist cache list pointer + */ +void insert_cache_into_list( cache_param_t *cache, cachelist_param_t *cachelist); + + +/** + * search a cache by target name + * + * @param[in] targetname target filename + * @param[in] cachelist cache list pointer + * @return found cache pointer + */ +cache_param_t * search_cache( const char targetname[], cachelist_param_t *cachelist); + + +/** + * search a cache by csn + * + * @param[in] csn codestream number + * @param[in] cachelist cache list pointer + * @return found cache pointer + */ +cache_param_t * search_cacheBycsn( int csn, cachelist_param_t *cachelist); + + +/** + * search a cache by cid + * + * @param[in] cid channel identifer + * @param[in] cachelist cache list pointer + * @return found cache pointer + */ +cache_param_t * search_cacheBycid( const char cid[], cachelist_param_t *cachelist); + + +/** + * search a cache by tid + * + * @param[in] tid target identifer + * @param[in] cachelist cache list pointer + * @return found cache pointer + */ +cache_param_t * search_cacheBytid( const char tid[], cachelist_param_t *cachelist); + +/** + * add cid into a cache + * + * @param[in] cid channel identifier + * @param[in] cache cache pointer + */ +void add_cachecid( const char *cid, cache_param_t *cache); + + +/** + * update tid of a cache + * + * @param[in] tid target identifier + * @param[in] cache cache pointer + */ +void update_cachetid( const char *tid, cache_param_t *cache); + + +/** + * remove cid in cache + * + * @param[in] cid channel identifier + * @param[in] cachelist cachelist pointer + */ +void remove_cachecid( const char *cid, cachelist_param_t *cachelist); + + +/** + * print cache parameters + * + * @param[in] cache cache pointer + */ +void print_cache( cache_param_t *cache); + +/** + * print all cache parameters + * + * @param[in] cachelist cache list pointer + */ +void print_allcache( cachelist_param_t *cachelist); + +#endif /* !CACHE_MANAGER_H_ */ diff --git a/src/lib/openjpip/cachemodel_manager.c b/src/lib/openjpip/cachemodel_manager.c new file mode 100644 index 00000000..1a84a6b8 --- /dev/null +++ b/src/lib/openjpip/cachemodel_manager.c @@ -0,0 +1,236 @@ +/* + * $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 "cachemodel_manager.h" +#include "faixbox_manager.h" +#include "opj_inttypes.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*/ + + +cachemodellist_param_t * gene_cachemodellist(void) +{ + cachemodellist_param_t *cachemodellist; + + cachemodellist = (cachemodellist_param_t *)malloc( sizeof(cachemodellist_param_t)); + + cachemodellist->first = NULL; + cachemodellist->last = NULL; + + return cachemodellist; +} + +cachemodel_param_t * gene_cachemodel( cachemodellist_param_t *cachemodellist, target_param_t *target, bool reqJPP) +{ + cachemodel_param_t *cachemodel; + faixbox_param_t *tilepart; + faixbox_param_t *precpacket; + size_t numOfelem; + Byte8_t numOftiles; + int i; + + cachemodel = (cachemodel_param_t *)malloc( sizeof(cachemodel_param_t)); + + refer_target( target, &cachemodel->target); + + if( reqJPP){ + if( target->jppstream) + cachemodel->jppstream = true; + else + cachemodel->jppstream = false; + } else{ /* reqJPT */ + if( target->jptstream) + cachemodel->jppstream = false; + else + cachemodel->jppstream = true; + } + + cachemodel->mhead_model = false; + + tilepart = target->codeidx->tilepart; + numOftiles = get_m( tilepart); + numOfelem = get_nmax( tilepart)*numOftiles; + cachemodel->tp_model = (bool *)calloc( 1, numOfelem*sizeof(bool)); + cachemodel->th_model = (bool *)calloc( 1, numOftiles*sizeof(bool)); + cachemodel->pp_model = (bool **)malloc( target->codeidx->SIZ.Csiz*sizeof(bool *)); + for( i=0; i<target->codeidx->SIZ.Csiz; i++){ + precpacket = target->codeidx->precpacket[i]; + cachemodel->pp_model[i] = (bool *)calloc( 1, get_nmax(precpacket)*get_m(precpacket)*sizeof(bool)); + } + cachemodel->next = NULL; + + if( cachemodellist){ + if( cachemodellist->first) /* there are one or more entries */ + cachemodellist->last->next = cachemodel; + else /* first entry */ + cachemodellist->first = cachemodel; + cachemodellist->last = cachemodel; + } + +#ifndef SERVER + fprintf( logstream, "local log: cachemodel generated\n"); +#endif + + return cachemodel; +} + +void print_cachemodel( cachemodel_param_t cachemodel) +{ + target_param_t *target; + Byte8_t TPnum; /* num of tile parts in each tile */ + Byte8_t Pmax; /* max num of packets per tile */ + Byte8_t i, j, k; + int n; /* FIXME: Is this large enough ? */ + + target = cachemodel.target; + + fprintf( logstream, "target: %s\n", target->targetname); + fprintf( logstream, "\t main header model: %d\n", cachemodel.mhead_model); + + fprintf( logstream, "\t tile part model:\n"); + TPnum = get_nmax( target->codeidx->tilepart); + + for( i=0, n=0; i<target->codeidx->SIZ.YTnum; i++){ + for( j=0; j<target->codeidx->SIZ.XTnum; j++){ + for( k=0; k<TPnum; k++) + fprintf( logstream, "%d", cachemodel.tp_model[n++]); + fprintf( logstream, " "); + } + fprintf( logstream, "\n"); + } + + fprintf( logstream, "\t tile header and precinct packet model:\n"); + for( i=0; i<target->codeidx->SIZ.XTnum*target->codeidx->SIZ.YTnum; i++){ + fprintf( logstream, "\t tile.%" PRIu64 " %d\n", i, cachemodel.th_model[i]); + for( j=0; j<target->codeidx->SIZ.Csiz; j++){ + fprintf( logstream, "\t compo.%" PRIu64 ": ", j); + Pmax = get_nmax( target->codeidx->precpacket[j]); + for( k=0; k<Pmax; k++) + fprintf( logstream, "%d", cachemodel.pp_model[j][i*Pmax+k]); + fprintf( logstream, "\n"); + } + } +} + +cachemodel_param_t * search_cachemodel( target_param_t *target, cachemodellist_param_t *cachemodellist) +{ + cachemodel_param_t *foundcachemodel; + + foundcachemodel = cachemodellist->first; + + while( foundcachemodel != NULL){ + + if( foundcachemodel->target == target) + return foundcachemodel; + + foundcachemodel = foundcachemodel->next; + } + return NULL; +} + +void delete_cachemodellist( cachemodellist_param_t **cachemodellist) +{ + cachemodel_param_t *cachemodelPtr, *cachemodelNext; + + cachemodelPtr = (*cachemodellist)->first; + while( cachemodelPtr != NULL){ + cachemodelNext=cachemodelPtr->next; + delete_cachemodel( &cachemodelPtr); + cachemodelPtr=cachemodelNext; + } + free(*cachemodellist); +} + +void delete_cachemodel( cachemodel_param_t **cachemodel) +{ + int i; + + unrefer_target( (*cachemodel)->target); + + free( (*cachemodel)->tp_model); + free( (*cachemodel)->th_model); + + for( i=0; i<(*cachemodel)->target->codeidx->SIZ.Csiz; i++) + free( (*cachemodel)->pp_model[i]); + free( (*cachemodel)->pp_model); + +#ifndef SERVER + fprintf( logstream, "local log: cachemodel deleted\n"); +#endif + free( *cachemodel); +} + +bool is_allsent( cachemodel_param_t cachemodel) +{ + target_param_t *target; + Byte8_t TPnum; /* num of tile parts in each tile */ + Byte8_t Pmax; /* max num of packets per tile */ + Byte8_t i, j, k; + int n; /* FIXME: is this large enough ? */ + + target = cachemodel.target; + + if( !cachemodel.mhead_model) + return false; + + TPnum = get_nmax( target->codeidx->tilepart); + + if( cachemodel.jppstream){ + for( i=0; i<target->codeidx->SIZ.XTnum*target->codeidx->SIZ.YTnum; i++){ + if( !cachemodel.th_model[i]) + return false; + + for( j=0; j<target->codeidx->SIZ.Csiz; j++){ + Pmax = get_nmax( target->codeidx->precpacket[j]); + for( k=0; k<Pmax; k++) + if( !cachemodel.pp_model[j][i*Pmax+k]) + return false; + } + } + return true; + } + else{ + for( i=0, n=0; i<target->codeidx->SIZ.YTnum; i++) + for( j=0; j<target->codeidx->SIZ.XTnum; j++) + for( k=0; k<TPnum; k++) + if( !cachemodel.tp_model[n++]) + return false; + return true; + } +} diff --git a/src/lib/openjpip/cachemodel_manager.h b/src/lib/openjpip/cachemodel_manager.h new file mode 100644 index 00000000..2c9dc540 --- /dev/null +++ b/src/lib/openjpip/cachemodel_manager.h @@ -0,0 +1,115 @@ +/* + * $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. + */ + +#ifndef CACHEMODEL_MANAGER_H_ +# define CACHEMODEL_MANAGER_H_ + +#include "bool.h" +#include "target_manager.h" + +/** Cache model parameters*/ +typedef struct cachemodel_param{ + target_param_t *target; /**< reference pointer to the target*/ + bool jppstream; /**< return type, true: JPP-stream, false: JPT-stream*/ + bool mhead_model; /**< main header model, if sent, 1, else 0*/ + bool *tp_model; /**< dynamic array pointer of tile part model, if sent, 1, else 0*/ + bool *th_model; /**< dynamic array pointer of tile header model*/ + bool **pp_model; /**< dynamic array pointer of precint packet model*/ + struct cachemodel_param *next; /**< pointer to the next cache model*/ +} cachemodel_param_t; + +/** Cache model list parameters*/ +typedef struct cachemodellist_param{ + cachemodel_param_t *first; /**< first cache model pointer of the list*/ + cachemodel_param_t *last; /**< last cache model pointer of the list*/ +} cachemodellist_param_t; + + +/** + * generate a cache model list + * + * @return pointer to the generated cache model list + */ +cachemodellist_param_t * gene_cachemodellist(void); + +/** + * generate a cache model under a list + * + * @param[in] cachemodellist cachemodel list to insert the generated cache model, NULL for stateless + * @param[in] target pointer the reference target + * @param[in] reqJPP if JPP-stream is desired true, JPT-stream false + * @return pointer to the generated cache model + */ +cachemodel_param_t * gene_cachemodel( cachemodellist_param_t *cachemodellist, target_param_t *target, bool reqJPP); + + +/** + * print cache model + * + * @param[in] cachemodel cache model + */ +void print_cachemodel( cachemodel_param_t cachemodel); + + +/** + * search a cache model of a target + * + * @param[in] target refering target + * @param[in] cachemodellist cache model list + * @return found cache model pointer + */ +cachemodel_param_t * search_cachemodel( target_param_t *target, cachemodellist_param_t *cachemodellist); + + +/** + * check if all data has been sent + * + * @param[in] cachemodel cache model + * @return true if sent all, false otherwise + */ +bool is_allsent( cachemodel_param_t cachemodel); + + +/** + * delete a cache model + * + * @param[in] cachemodel address of the cachemodel pointer + */ +void delete_cachemodel( cachemodel_param_t **cachemodel); + +/** + * delete cachemodel list + * + * @param[in,out] cachemodellist address of the cachemodel list pointer + */ +void delete_cachemodellist( cachemodellist_param_t **cachemodellist); + + +#endif /* !CACHEMODEL_MANAGER_H_ */ diff --git a/src/lib/openjpip/channel_manager.c b/src/lib/openjpip/channel_manager.c new file mode 100644 index 00000000..313f8ced --- /dev/null +++ b/src/lib/openjpip/channel_manager.c @@ -0,0 +1,180 @@ +/* + * $Id: channel_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "channel_manager.h" +#ifdef _WIN32 +#define snprintf _snprintf /* Visual Studio */ +#endif + +#ifdef SERVER +#include "fcgi_stdio.h" +#define logstream FCGI_stdout +#else +#define FCGI_stdout stdout +#define FCGI_stderr stderr +#define logstream stderr +#endif /*SERVER */ + +channellist_param_t * gene_channellist(void) +{ + channellist_param_t *channellist; + + channellist = (channellist_param_t *)malloc( sizeof(channellist_param_t)); + + channellist->first = NULL; + channellist->last = NULL; + + return channellist; +} + +channel_param_t * gene_channel( query_param_t query_param, auxtrans_param_t auxtrans, cachemodel_param_t *cachemodel, channellist_param_t *channellist) +{ + channel_param_t *channel; + const char transport[4][10] = { "non", "http", "http-tcp", "http-udp"}; + + if( !cachemodel){ + fprintf( FCGI_stdout, "Status: 404\r\n"); + fprintf( FCGI_stdout, "Reason: cnew cancelled\r\n"); + return NULL; + } + + channel = (channel_param_t *)malloc( sizeof(channel_param_t)); + channel->cachemodel = cachemodel; + + /* set channel ID and get present time */ + snprintf( channel->cid, MAX_LENOFCID, "%x%x", (unsigned int)time( &channel->start_tm), (unsigned int)rand()); + + channel->aux = query_param.cnew; + + /* only tcp implemented for now */ + if( channel->aux == udp) + channel->aux = tcp; + + channel->next=NULL; + + set_channel_variable_param( query_param, channel); + + if( channellist->first != NULL) + channellist->last->next = channel; + else + channellist->first = channel; + channellist->last = channel; + + fprintf( FCGI_stdout, "JPIP-cnew: cid=%s", channel->cid); + fprintf( FCGI_stdout, ",transport=%s", transport[channel->aux]); + + if( channel->aux == tcp || channel->aux == udp) + fprintf( FCGI_stdout, ",auxport=%d", channel->aux==tcp ? auxtrans.tcpauxport : auxtrans.udpauxport); + + fprintf( FCGI_stdout, "\r\n"); + + return channel; +} + + +void set_channel_variable_param( query_param_t query_param, channel_param_t *channel) +{ + /* set roi information */ + (void)query_param; + (void)channel; +} + + +void delete_channel( channel_param_t **channel, channellist_param_t *channellist) +{ + channel_param_t *ptr; + + if( *channel == channellist->first) + channellist->first = (*channel)->next; + else{ + ptr = channellist->first; + while( ptr->next != *channel){ + ptr=ptr->next; + } + + ptr->next = (*channel)->next; + + if( *channel == channellist->last) + channellist->last = ptr; + } +#ifndef SERVER + fprintf( logstream, "local log: channel: %s deleted\n", (*channel)->cid); +#endif + free(*channel); +} + +void delete_channellist( channellist_param_t **channellist) +{ + channel_param_t *channelPtr, *channelNext; + + channelPtr = (*channellist)->first; + while( channelPtr != NULL){ + channelNext=channelPtr->next; +#ifndef SERVER + fprintf( logstream, "local log: channel %s deleted!\n", channelPtr->cid); +#endif + free(channelPtr); + channelPtr=channelNext; + } + free( *channellist); +} + +void print_allchannel( channellist_param_t *channellist) +{ + channel_param_t *ptr; + + ptr = channellist->first; + while( ptr != NULL){ + fprintf( logstream,"channel-ID=%s \t target=%s\n", ptr->cid, ptr->cachemodel->target->targetname); + ptr=ptr->next; + } +} + +channel_param_t * search_channel( const char cid[], channellist_param_t *channellist) +{ + channel_param_t *foundchannel; + + foundchannel = channellist->first; + + while( foundchannel != NULL){ + + if( strcmp( cid, foundchannel->cid) == 0) + return foundchannel; + + foundchannel = foundchannel->next; + } + fprintf( FCGI_stdout, "Status: 503\r\n"); + fprintf( FCGI_stdout, "Reason: Channel %s not found in this session\r\n", cid); + + return NULL; +} diff --git a/src/lib/openjpip/channel_manager.h b/src/lib/openjpip/channel_manager.h new file mode 100644 index 00000000..79cc0160 --- /dev/null +++ b/src/lib/openjpip/channel_manager.h @@ -0,0 +1,120 @@ +/* + * $Id: channel_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef CHANNEL_MANAGER_H_ +# define CHANNEL_MANAGER_H_ + +#include <time.h> +#include "query_parser.h" +#include "cachemodel_manager.h" +#include "auxtrans_manager.h" + +/** maximum length of channel identifier*/ +#define MAX_LENOFCID 30 + +/** Channel parameters*/ +typedef struct channel_param{ + cachemodel_param_t *cachemodel; /**< reference pointer to the cache model*/ + char cid[MAX_LENOFCID]; /**< channel identifier*/ + cnew_transport_t aux; /**< auxiliary transport*/ + /* - a record of the client's capabilities and preferences to the extent that the server queues requests*/ + time_t start_tm; /**< starting time*/ + struct channel_param *next; /**< pointer to the next channel*/ +} channel_param_t; + + +/** Channel list parameters*/ +typedef struct channellist_param{ + channel_param_t *first; /**< first channel pointer of the list*/ + channel_param_t *last; /**< last channel pointer of the list*/ +} channellist_param_t; + + +/** + * generate a channel list + * + * @return pointer to the generated channel list + */ +channellist_param_t * gene_channellist(void); + + +/** + * generate a channel under the channel list + * + * @param[in] query_param query parameters + * @param[in] auxtrans auxiliary transport + * @param[in] cachemodel reference cachemodel + * @param[in] channellist channel list pointer + * @return pointer to the generated channel + */ +channel_param_t * gene_channel( query_param_t query_param, auxtrans_param_t auxtrans, cachemodel_param_t *cachemodel, channellist_param_t *channellist); + +/** + * set channel variable parameters + * + * @param[in] query_param query parameters + * @param[in,out] channel pointer to the modifying channel + */ +void set_channel_variable_param( query_param_t query_param, channel_param_t *channel); + +/** + * delete a channel + * + * @param[in] channel address of the deleting channel pointer + * @param[in,out] channellist channel list pointer + */ +void delete_channel( channel_param_t **channel, channellist_param_t *channellist); + + +/** + * delete channel list + * + * @param[in,out] channellist address of the channel list pointer + */ +void delete_channellist( channellist_param_t **channellist); + + +/** + * print all channel parameters + * + * @param[in] channellist channel list pointer + */ +void print_allchannel( channellist_param_t *channellist); + + +/** + * search a channel by channel ID + * + * @param[in] cid channel identifier + * @param[in] channellist channel list pointer + * @return found channel pointer + */ +channel_param_t * search_channel( const char cid[], channellist_param_t *channellist); +#endif /* !CHANNEL_MANAGER_H_ */ diff --git a/src/lib/openjpip/codestream_manager.c b/src/lib/openjpip/codestream_manager.c new file mode 100644 index 00000000..d7797c13 --- /dev/null +++ b/src/lib/openjpip/codestream_manager.c @@ -0,0 +1,81 @@ +/* + * $Id: codestream_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 "codestream_manager.h" +#include "opj_inttypes.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 */ + +codestream_param_t set_codestream( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length) +{ + codestream_param_t cs; + + cs.fd = fd; + cs.offset = offset; + cs.length = length; + + return cs; +} + +Byte_t * fetch_codestreambytes( codestream_param_t *cs, OPJ_OFF_T offset, OPJ_SIZE_T size) +{ + return fetch_bytes( cs->fd, cs->offset+offset, size); +} + +Byte_t fetch_codestream1byte( codestream_param_t *cs, OPJ_OFF_T offset) +{ + return fetch_1byte( cs->fd, cs->offset+offset); +} + +Byte2_t fetch_codestream2bytebigendian( codestream_param_t *cs, OPJ_OFF_T offset) +{ + return fetch_2bytebigendian( cs->fd, cs->offset+offset); +} + +Byte4_t fetch_codestream4bytebigendian( codestream_param_t *cs, OPJ_OFF_T offset) +{ + return fetch_4bytebigendian( cs->fd, cs->offset+offset); +} + +void print_codestream( codestream_param_t cs) +{ + fprintf( logstream, "codestream info:\n" + "\t fd: %d\n" + "\t offset: %#" PRIx64 "\n" + "\t length: %#" PRIx64 "\n", cs.fd, cs.offset, cs.length); +} diff --git a/src/lib/openjpip/codestream_manager.h b/src/lib/openjpip/codestream_manager.h new file mode 100644 index 00000000..b600d8e5 --- /dev/null +++ b/src/lib/openjpip/codestream_manager.h @@ -0,0 +1,101 @@ +/* + * $Id: codestream_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef CODESTREAM_MANAGER_H_ +# define CODESTREAM_MANAGER_H_ + +#include "byte_manager.h" + +/** codestream parameters*/ +typedef struct codestream_param{ + int fd; /**< file descriptor*/ + OPJ_OFF_T offset; /**< byte position of DBox (Box Contents) in the file*/ + Byte8_t length; /**< content length*/ +} codestream_param_t; + + +/** + * set codestream parameters from inputs + * + * @param[in] fd file descriptor + * @param[in] offset offset in the file + * @param[in] length codestream length + * @return structure of generated codestream parameters + */ +codestream_param_t set_codestream( int fd, OPJ_OFF_T offset, OPJ_SIZE_T length); + + +/** + * fetch Codestream bytes of data in file stream + * + * @param[in] cs codestream pointer + * @param[in] offset start Byte position in codestream + * @param[in] size Byte length + * @return pointer to the fetched data + */ +Byte_t * fetch_codestreambytes( codestream_param_t *cs, OPJ_OFF_T offset, OPJ_SIZE_T size); + +/** + * fetch Codestream 1-byte Byte code in file stream + * + * @param[in] cs codestream pointer + * @param[in] offset start Byte position in codestream + * @return fetched code + */ +Byte_t fetch_codestream1byte( codestream_param_t *cs, OPJ_OFF_T offset); + +/** + * fetch Codestream 2-byte big endian Byte codes in file stream + * + * @param[in] cs codestream pointer + * @param[in] offset start Byte position in codestream + * @return fetched code + */ +Byte2_t fetch_codestream2bytebigendian( codestream_param_t *cs, OPJ_OFF_T offset); + +/** + * fetch Codestream 4-byte big endian Byte codes in file stream + * + * @param[in] cs codestream pointer + * @param[in] offset start Byte position in codestream + * @return fetched code + */ +Byte4_t fetch_codestream4bytebigendian( codestream_param_t *cs, OPJ_OFF_T offset); + + +/** + * print codestream parameters + * + * @param[in] cs codestream + */ +void print_codestream( codestream_param_t cs); + + +#endif /* !CODESTREAM_MANAGER_H_ */ diff --git a/src/lib/openjpip/dec_clientmsg_handler.c b/src/lib/openjpip/dec_clientmsg_handler.c new file mode 100644 index 00000000..20bd4f2b --- /dev/null +++ b/src/lib/openjpip/dec_clientmsg_handler.c @@ -0,0 +1,253 @@ +/* + * $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 <assert.h> +#include <limits.h> +#include "dec_clientmsg_handler.h" +#include "ihdrbox_manager.h" +#include "jpipstream_manager.h" +#include "jp2k_encoder.h" +#include "opj_inttypes.h" + +void handle_JPIPstreamMSG( SOCKET connected_socket, cachelist_param_t *cachelist, + Byte_t **jpipstream, OPJ_SIZE_T *streamlen, msgqueue_param_t *msgqueue) +{ + Byte_t *newjpipstream; + OPJ_SIZE_T newstreamlen = 0; + cache_param_t *cache; + char *target, *tid, *cid; + metadatalist_param_t *metadatalist; + + newjpipstream = receive_JPIPstream( connected_socket, &target, &tid, &cid, &newstreamlen); + + fprintf( stderr, "newjpipstream length: %" PRIu64 "\n", newstreamlen); + + parse_JPIPstream( newjpipstream, newstreamlen, (OPJ_OFF_T)*streamlen, msgqueue); + + *jpipstream = update_JPIPstream( newjpipstream, newstreamlen, *jpipstream, streamlen); + free( newjpipstream); + + metadatalist = gene_metadatalist(); + parse_metamsg( msgqueue, *jpipstream, *streamlen, metadatalist); + + assert( msgqueue->last ); + assert( msgqueue->last->csn < INT_MAX ); + /* cid registration*/ + if( target != NULL){ + if((cache = search_cache( target, cachelist))){ + if( tid != NULL) + update_cachetid( tid, cache); + if( cid != NULL) + add_cachecid( cid, cache); + } + else{ + cache = gene_cache( target, (int)msgqueue->last->csn, tid, cid); + insert_cache_into_list( cache, cachelist); + } + } + else + cache = search_cacheBycsn( (int)msgqueue->last->csn, cachelist); + + if( cache->metadatalist) + delete_metadatalist( &cache->metadatalist); + cache->metadatalist = metadatalist; + + if( target) free( target); + if( tid) free( tid); + if( cid) free( cid); + + 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 *CIDorTID, tmp[10]; + cache_param_t *cache; + int fw, fh; + int maxval; + + CIDorTID = receive_string( connected_socket); + + if(!(cache = search_cacheBycid( CIDorTID, cachelist))) + if(!(cache = search_cacheBytid( CIDorTID, cachelist))){ + free( CIDorTID); + return; + } + + free( CIDorTID); + + receive_line( connected_socket, tmp); + fw = atoi( tmp); + + receive_line( connected_socket, tmp); + fh = atoi( tmp); + + ihdrbox = NULL; + assert( cache->csn >= 0 ); + pnmstream = jpipstream_to_pnm( jpipstream, msgqueue, (Byte8_t)cache->csn, fw, fh, &ihdrbox); + + maxval = ihdrbox->bpc > 8 ? 255 : (1 << ihdrbox->bpc) - 1; + send_PNMstream( connected_socket, pnmstream, ihdrbox->width, ihdrbox->height, ihdrbox->nc, (Byte_t)maxval ); + + free( ihdrbox); + free( pnmstream); +} + +void handle_XMLreqMSG( SOCKET connected_socket, Byte_t *jpipstream, cachelist_param_t *cachelist) +{ + char *cid; + cache_param_t *cache; + boxcontents_param_t *boxcontents; + Byte_t *xmlstream; + + cid = receive_string( connected_socket); + + if(!(cache = search_cacheBycid( cid, cachelist))){ + free( cid); + return; + } + + free( cid); + + boxcontents = cache->metadatalist->last->boxcontents; + 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, *tid = NULL; + cache_param_t *cache; + OPJ_SIZE_T tidlen = 0; + + target = receive_string( connected_socket); + cache = search_cache( target, cachelist); + + free( target); + + 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, *cid = NULL; + cache_param_t *cache; + OPJ_SIZE_T cidlen = 0; + + target = receive_string( connected_socket); + cache = search_cache( target, cachelist); + + free( target); + + 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; + + cid = receive_string( connected_socket); + remove_cachecid( cid, cachelist); + response_signal( connected_socket, true); + + free( cid); +} + +void handle_SIZreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, cachelist_param_t *cachelist) +{ + char *tid, *cid; + cache_param_t *cache; + Byte4_t width, height; + + tid = receive_string( connected_socket); + cid = receive_string( connected_socket); + + cache = NULL; + + if( tid[0] != '0') + cache = search_cacheBytid( tid, cachelist); + + if( !cache && cid[0] != '0') + cache = search_cacheBycid( cid, cachelist); + + free( tid); + free( cid); + + width = height = 0; + if( cache){ + assert( cache->csn >= 0); + if( !cache->ihdrbox) + cache->ihdrbox = get_SIZ_from_jpipstream( jpipstream, msgqueue, (Byte8_t)cache->csn); + width = cache->ihdrbox->width; + height = cache->ihdrbox->height; + } + send_SIZstream( connected_socket, width, height); +} + +void handle_JP2saveMSG( SOCKET connected_socket, cachelist_param_t *cachelist, msgqueue_param_t *msgqueue, Byte_t *jpipstream) +{ + char *cid; + cache_param_t *cache; + Byte_t *jp2stream; + Byte8_t jp2len; + + cid = receive_string( connected_socket); + if(!(cache = search_cacheBycid( cid, cachelist))){ + free( cid); + return; + } + + free( cid); + + assert( cache->csn >= 0); + jp2stream = recons_jp2( msgqueue, jpipstream, (Byte8_t)cache->csn, &jp2len); + + if( jp2stream){ + save_codestream( jp2stream, jp2len, "jp2"); + free( jp2stream); + } +} diff --git a/src/lib/openjpip/dec_clientmsg_handler.h b/src/lib/openjpip/dec_clientmsg_handler.h new file mode 100644 index 00000000..7929207a --- /dev/null +++ b/src/lib/openjpip/dec_clientmsg_handler.h @@ -0,0 +1,113 @@ +/* + * $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 "imgsock_manager.h" +#include "cache_manager.h" +#include "byte_manager.h" +#include "msgqueue_manager.h" + +/** + * 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, OPJ_SIZE_T *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 SIZ request message + * + * @param[in] connected_socket socket descriptor + * @param[in,out] cachelist cache list pointer + */ +void handle_SIZreqMSG( SOCKET connected_socket, Byte_t *jpipstream, msgqueue_param_t *msgqueue, 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 /* !DEC_CLIENTMSG_HANDLER_H_ */ diff --git a/src/lib/openjpip/faixbox_manager.c b/src/lib/openjpip/faixbox_manager.c new file mode 100644 index 00000000..3c443832 --- /dev/null +++ b/src/lib/openjpip/faixbox_manager.c @@ -0,0 +1,195 @@ +/* + * $Id: faixbox_manager.c 53 2011-05-09 16:55:39Z kaori $ + * + * 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 "faixbox_manager.h" +#include "opj_inttypes.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*/ + +faixbox_param_t * gene_faixbox( box_param_t *box) +{ + faixbox_param_t *faix; + size_t numOfelem; + long pos = 0; + + faix = ( faixbox_param_t *)malloc( sizeof(faixbox_param_t)); + + faix->version = fetch_DBox1byte( box, (pos+=1)-1); + + if( 3< faix->version){ + fprintf( FCGI_stderr, "Error: version %d in faix box is reserved for ISO use.\n", faix->version); + free(faix); + return NULL; + } + + if( faix->version%2){ + subfaixbox8_param_t *subfaixbox; + size_t i; + + faix->subfaixbox.byte8_params = (subfaixbox8_param_t *)malloc( sizeof(subfaixbox8_param_t)); + + subfaixbox = faix->subfaixbox.byte8_params; + subfaixbox->nmax = fetch_DBox8bytebigendian( box, (pos+=8)-8); + subfaixbox->m = fetch_DBox8bytebigendian( box, (pos+=8)-8); + + numOfelem = subfaixbox->nmax*subfaixbox->m; + + subfaixbox->elem = ( faixelem8_param_t *)malloc( numOfelem*sizeof(faixelem8_param_t)); + + if( faix->version == 3) + subfaixbox->aux = ( Byte4_t *)malloc( numOfelem*sizeof(Byte4_t)); + + for( i=0; i<numOfelem; i++){ + subfaixbox->elem[i].off = fetch_DBox8bytebigendian( box, (pos+=8)-8); + subfaixbox->elem[i].len = fetch_DBox8bytebigendian( box, (pos+=8)-8); + if( faix->version == 3) + subfaixbox->aux[i] = fetch_DBox4bytebigendian( box, (pos+=4)-4); + } + } + else{ + subfaixbox4_param_t *subfaixbox; + size_t i; + + faix->subfaixbox.byte4_params = (subfaixbox4_param_t *)malloc( sizeof(subfaixbox4_param_t)); + + subfaixbox = faix->subfaixbox.byte4_params; + subfaixbox->nmax = fetch_DBox4bytebigendian( box, (pos+=4)-4); + subfaixbox->m = fetch_DBox4bytebigendian( box, (pos+=4)-4); + + numOfelem = subfaixbox->nmax*subfaixbox->m; + + subfaixbox->elem = ( faixelem4_param_t *)malloc( numOfelem*sizeof(faixelem4_param_t)); + + if( faix->version == 2) + subfaixbox->aux = ( Byte4_t *)malloc( numOfelem*sizeof(Byte4_t)); + + for( i=0; i<numOfelem; i++){ + subfaixbox->elem[i].off = fetch_DBox4bytebigendian( box, (pos+=4)-4); + subfaixbox->elem[i].len = fetch_DBox4bytebigendian( box, (pos+=4)-4); + if( faix->version == 2) + subfaixbox->aux[i] = fetch_DBox4bytebigendian( box, (pos+=4)-4); + } + } + return faix; +} + +void print_faixbox( faixbox_param_t *faix) +{ + Byte8_t i, j; + + fprintf( logstream, "faix box info\n"); + fprintf( logstream, "\tversion: %d\n", faix->version); + + fprintf( logstream, "\t nmax: %#" PRIx64 " = %" PRId64 "\n", get_nmax( faix), get_nmax( faix)); + fprintf( logstream, "\t m: %#" PRIx64 " = %" PRId64 "\n", get_m( faix), get_m( faix)); + + for( i=0; i<get_m( faix); i++){ + for( j=0; j<get_nmax( faix); j++){ + fprintf( logstream, "\t off = %#" PRIx64 ", len = %#" PRIx64 "", get_elemOff( faix, j, i), get_elemLen( faix, j, i)); + if( 2 <= faix->version) + fprintf( logstream, ", aux = %#x", get_elemAux( faix, j, i)); + fprintf( logstream, "\n"); + } + fprintf( logstream, "\n"); + } +} + +void delete_faixbox( faixbox_param_t **faix) +{ + if((*faix)->version%2){ + free((*faix)->subfaixbox.byte8_params->elem); + if( (*faix)->version == 3) + free((*faix)->subfaixbox.byte8_params->aux); + free((*faix)->subfaixbox.byte8_params); + } + else{ + free((*faix)->subfaixbox.byte4_params->elem); + if( (*faix)->version == 2) + free((*faix)->subfaixbox.byte4_params->aux); + free((*faix)->subfaixbox.byte4_params); + } + free( *faix); +} + +Byte8_t get_nmax( faixbox_param_t *faix) +{ + if( faix->version%2) + return faix->subfaixbox.byte8_params->nmax; + else + return (Byte8_t)faix->subfaixbox.byte4_params->nmax; +} + +Byte8_t get_m( faixbox_param_t *faix) +{ + if( faix->version%2) + return faix->subfaixbox.byte8_params->m; + else + return (Byte8_t)faix->subfaixbox.byte4_params->m; +} + +Byte8_t get_elemOff( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id) +{ + Byte8_t nmax = get_nmax( faix); + if( faix->version%2) + return faix->subfaixbox.byte8_params->elem[ row_id*nmax+elem_id].off; + else + return (Byte8_t)faix->subfaixbox.byte4_params->elem[ row_id*nmax+elem_id].off; +} + +Byte8_t get_elemLen( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id) +{ + Byte8_t nmax = get_nmax( faix); + if( faix->version%2) + return faix->subfaixbox.byte8_params->elem[ row_id*nmax+elem_id].len; + else + return (Byte8_t)faix->subfaixbox.byte4_params->elem[ row_id*nmax+elem_id].len; +} + +Byte4_t get_elemAux( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id) +{ + Byte8_t nmax; + if( faix->version <2) + return (Byte4_t)-1; + + nmax = get_nmax( faix); + if( faix->version%2) + return faix->subfaixbox.byte8_params->aux[ row_id*nmax+elem_id]; + else + return faix->subfaixbox.byte4_params->aux[ row_id*nmax+elem_id]; +} diff --git a/src/lib/openjpip/faixbox_manager.h b/src/lib/openjpip/faixbox_manager.h new file mode 100644 index 00000000..45ea8c3e --- /dev/null +++ b/src/lib/openjpip/faixbox_manager.h @@ -0,0 +1,146 @@ +/* + * $Id: faixbox_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef FAIXBOX_MANAGER_H_ +# define FAIXBOX_MANAGER_H_ + +#include "byte_manager.h" +#include "box_manager.h" + +/** 4byte parameters of a faix element*/ +typedef struct faixelem4_param{ + Byte4_t off; /**< offset*/ + Byte4_t len; /**< length*/ +} faixelem4_param_t; + +/** 8byte parameters of a faix element*/ +typedef struct faixelem8_param{ + Byte8_t off; /**< offset*/ + Byte8_t len; /**< length*/ +} faixelem8_param_t; + +/** 4byte parameters of fragment array index box*/ +typedef struct subfaixbox4_param{ + Byte4_t nmax; /**< maximum number of valid elements in any row of the array*/ + Byte4_t m; /**< number of raws of the array*/ + faixelem4_param_t *elem; /**< dynamic array pointer of faix elements*/ + Byte4_t *aux; /**< dynamic array pointer of auxiliary*/ + /**info in each element for version 2 or 3*/ +} subfaixbox4_param_t; + +/** 8byte parameters of fragment array index box*/ +typedef struct subfaixbox8_param{ + Byte8_t nmax; /**< maximum number of valid elements in any row of the array*/ + Byte8_t m; /**< number of raws of the array*/ + faixelem8_param_t *elem; /**< dynamic array pointer of faix elements*/ + Byte4_t *aux; /**< dynamic array pointer of auxiliary*/ + /**info in each element for version 2 or 3*/ +} subfaixbox8_param_t; + +/** variable sized parameters in fragment array index box*/ +typedef union subfaixbox_param{ + subfaixbox4_param_t *byte4_params; /**< parameters with 4byte codes for version 0 or 2*/ + subfaixbox8_param_t *byte8_params; /**< parameters with 8byte codes for version 1 or 3*/ +} subfaixbox_param_t; + +/** fragment array index box parameters*/ +/** I.3.2.4.2 Fragment Array Index box*/ +typedef struct faixbox_param{ + Byte_t version; /**< Refer to the Table I.3 - Version values*/ + subfaixbox_param_t subfaixbox; /**< rest information in faixbox*/ +} faixbox_param_t; + + +/** + * generate faix box + * + * @param[in] box pointer to the reference faix_box + * @return generated faixbox + */ +faixbox_param_t * gene_faixbox( box_param_t *box); + + +/** + * print faix box parameters + * + * @param[in] faix faix box pointer + */ +void print_faixbox( faixbox_param_t *faix); + + +/** + * delete faix box + * + * @param[in,out] faix addressof the faixbox pointer + */ +void delete_faixbox( faixbox_param_t **faix); + +/** + * get nmax parameter value from faix box + * + * @param[in] faix faix box pointer + */ +Byte8_t get_nmax( faixbox_param_t *faix); + +/** + * get m parameter value from faix box + * + * @param[in] faix faix box pointer + */ +Byte8_t get_m( faixbox_param_t *faix); + +/** + * get offset of a element from faix box + * + * @param[in] faix faix box pointer + * @param[in] elem_id element id in a row (0<= <nmax) + * @param[in] row_id row id (0<= <m) + */ +Byte8_t get_elemOff( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id); + +/** + * get length of a element from faix box + * + * @param[in] faix faix box pointer + * @param[in] elem_id element id in a row (0<= <nmax) + * @param[in] row_id row id (0<= <m) + */ +Byte8_t get_elemLen( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id); + +/** + * get aux of a element from faix box + * + * @param[in] faix faix box pointer + * @param[in] elem_id element id in a row (0<= <nmax) + * @param[in] row_id row id (0<= <m) + */ +Byte4_t get_elemAux( faixbox_param_t *faix, Byte8_t elem_id, Byte8_t row_id); + +#endif /* !FAIXBOX_MANAGER_H_ */ diff --git a/src/lib/openjpip/ihdrbox_manager.c b/src/lib/openjpip/ihdrbox_manager.c new file mode 100644 index 00000000..d501b612 --- /dev/null +++ b/src/lib/openjpip/ihdrbox_manager.c @@ -0,0 +1,78 @@ +/* + * $Id: ihdrbox_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 <assert.h> +#include "ihdrbox_manager.h" + +ihdrbox_param_t * gene_ihdrbox( metadatalist_param_t *metadatalist, Byte_t *jpipstream) +{ + ihdrbox_param_t *ihdrbox; + metadata_param_t *meta; + box_param_t *jp2h, *ihdr; + int bpc_val; + + jp2h = NULL; + meta = metadatalist->first; + while( meta){ + if( meta->boxlist){ + jp2h = search_box( "jp2h", meta->boxlist); + if( jp2h) + break; + } + meta = meta->next; + } + if( !jp2h){ + fprintf( stderr, "jp2h box not found\n"); + return NULL; + } + + ihdr = gene_boxbyTypeinStream( jpipstream, get_DBoxoff( jp2h), get_DBoxlen( jp2h), "ihdr"); + + if( !ihdr){ + fprintf( stderr, "ihdr box not found\n"); + return NULL; + } + + ihdrbox = (ihdrbox_param_t *)malloc( sizeof(ihdrbox_param_t)); + + ihdrbox->height = big4( jpipstream+get_DBoxoff(ihdr)); + ihdrbox->width = big4( jpipstream+get_DBoxoff(ihdr)+4); + ihdrbox->nc = big2( jpipstream+get_DBoxoff(ihdr)+8); + bpc_val = *(jpipstream+get_DBoxoff(ihdr)+10)+1; + assert( bpc_val >= 0 && bpc_val <= 255 ); + ihdrbox->bpc = (Byte_t)bpc_val; + + free( ihdr); + + return ihdrbox; +} + diff --git a/src/lib/openjpip/ihdrbox_manager.h b/src/lib/openjpip/ihdrbox_manager.h new file mode 100644 index 00000000..9fa9a830 --- /dev/null +++ b/src/lib/openjpip/ihdrbox_manager.h @@ -0,0 +1,56 @@ +/* + * $Id: ihdrbox_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef IHDRBOX_MANAGER_H_ +# define IHDRBOX_MANAGER_H_ + +#include "byte_manager.h" +#include "box_manager.h" +#include "metadata_manager.h" + +/** I.5.3.1 Image Header box*/ +typedef struct ihdrbox_param{ + Byte4_t height; + Byte4_t width; + Byte2_t nc; /**< number of components*/ + Byte_t bpc; /**< bits per component*/ +} ihdrbox_param_t; + +/** + * generate ihdr box + * + * @param[in] metadatalist metadata list pointer + * @param[in] jpipstream JPT/JPP stream + * @return pointer to generated ihdr box + */ +ihdrbox_param_t * gene_ihdrbox( metadatalist_param_t *metadatalist, Byte_t *jpipstream); + + +#endif /* !IHDRBOX_MANAGER_H_ */ diff --git a/src/lib/openjpip/imgreg_manager.c b/src/lib/openjpip/imgreg_manager.c new file mode 100644 index 00000000..3a713c32 --- /dev/null +++ b/src/lib/openjpip/imgreg_manager.c @@ -0,0 +1,157 @@ +/* + * $Id: imgreg_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 <math.h> +#include <stdlib.h> +#include <assert.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*/ + +imgreg_param_t map_viewin2imgreg( const int fx, const int fy, + const int rx, const int ry, + const int rw, const int rh, + const int XOsiz, const int YOsiz, + const int Xsiz, const int Ysiz, + const int numOfreslev) +{ + imgreg_param_t imgreg; + int px,py; + int xmax, ymax; + + imgreg.xosiz = XOsiz; + imgreg.yosiz = YOsiz; + imgreg.fx = fx; + imgreg.fy = fy; + imgreg.level = 0; + xmax = Xsiz; + ymax = Ysiz; + + find_level( numOfreslev, &imgreg.level, &imgreg.fx, &imgreg.fy, &imgreg.xosiz, &imgreg.yosiz, &xmax, &ymax); + + if( rx == -1 || ry == -1){ + imgreg.ox = 0; + imgreg.oy = 0; + } + else{ + imgreg.ox = rx*imgreg.fx/fx; + imgreg.oy = ry*imgreg.fy/fy; + } + + if( rw == -1 || rh == -1){ + imgreg.sx = imgreg.fx; + imgreg.sy = imgreg.fy; + } + else{ + px = (int)ceil((double)((rx+rw)*imgreg.fx)/(double)fx); + py = (int)ceil((double)((ry+rh)*imgreg.fy)/(double)fy); + + if( imgreg.fx < px) + px = imgreg.fx; + if( imgreg.fy < py) + py = imgreg.fy; + + imgreg.sx = px - imgreg.ox; + imgreg.sy = py - imgreg.oy; + } + + if( fx != imgreg.fx || fy != imgreg.fy) + fprintf( FCGI_stdout, "JPIP-fsiz: %d,%d\r\n", imgreg.fx, imgreg.fy); + + if( rw != imgreg.sx || rh != imgreg.sy) + fprintf( FCGI_stdout, "JPIP-rsiz: %d,%d\r\n", imgreg.sx, imgreg.sy); + + if( rx != imgreg.ox || ry != imgreg.oy) + fprintf( FCGI_stdout, "JPIP-roff: %d,%d\r\n", imgreg.ox, imgreg.oy); + + return imgreg; +} + +void find_level( int maxlev, int *lev, int *fx, int *fy, int *xmin, int *ymin, int *xmax, int *ymax) +{ + int xwidth = *xmax - *xmin; + int ywidth = *ymax - *ymin; + + /* Find smaller frame size for now (i.e. assume "round-down"). */ + if ((*fx < 1 && xwidth != 0) || (*fy < 1 && ywidth != 0)){ + fprintf( FCGI_stderr, "Frame size must be strictly positive"); + exit(-1); + } + else if( *lev < maxlev-1 && ( *fx < xwidth || *fy < ywidth)) { + /* Simulate the ceil function. */ + *xmin = (int)ceil((double)*xmin/(double)2.0); + *ymin = (int)ceil((double)*ymin/(double)2.0); + *xmax = (int)ceil((double)*xmax/(double)2.0); + *ymax = (int)ceil((double)*ymax/(double)2.0); + + (*lev) ++; + find_level ( maxlev, lev, fx, fy, xmin, ymin, xmax, ymax); + } else { + *fx = xwidth; + *fy = ywidth; + } +} + +int comp_decomplev( int fw, int fh, int Xsiz, int Ysiz) +{ + int level; + int xmin, xmax, ymin, ymax; + + level = 0; + xmin = ymin = 0; + xmax = Xsiz; + ymax = Ysiz; + + find_level( 1000, &level, &fw, &fh, &xmin, &ymin, &xmax, &ymax); + + assert( level >= 0 ); + return level; +} + +void print_imgreg( imgreg_param_t imgreg) +{ +#ifndef SERVER + fprintf( logstream, "codestream image region:\n"); + fprintf( logstream, "\t fsiz: %d, %d\n", imgreg.fx, imgreg.fy); + fprintf( logstream, "\t roff: %d, %d\n", imgreg.ox, imgreg.oy); + fprintf( logstream, "\t rsiz: %d, %d\n", imgreg.sx, imgreg.sy); + fprintf( logstream, "\t level: %d\n", imgreg.level); +#else + (void)imgreg; +#endif +} diff --git a/src/lib/openjpip/imgreg_manager.h b/src/lib/openjpip/imgreg_manager.h new file mode 100644 index 00000000..7967120b --- /dev/null +++ b/src/lib/openjpip/imgreg_manager.h @@ -0,0 +1,101 @@ +/* + * $Id: imgreg_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef IMGREG_MANAGER_H_ +# define IMGREG_MANAGER_H_ + +/** image region parameters */ +typedef struct imgreg_param{ + int xosiz, yosiz; /** offset from the origin of the reference grid + at the decomposition level */ + int fx, fy; /** frame size (fsiz) */ + int ox, oy; /** offset (roff) */ + int sx, sy; /** region size (rsiz) */ + int level; /** decomposition level */ +} imgreg_param_t; + + +/** + * map view-window requests to codestream image resolutions and regions + * + * @param[in] fx,fy frame size + * @param[in] rx,ry offset of region + * @param[in] rw,rh size of region + * @param[in] XOsiz,YOsiz offset from the origin of the reference grid to the left side of the image area + * @param[in] Xsiz,Ysiz size of the reference grid + * @param[in] numOfreslev number of resolution levels + * @return structure of image region parameters + */ +imgreg_param_t map_viewin2imgreg( const int fx, const int fy, + const int rx, const int ry, + const int rw, const int rh, + const int XOsiz, const int YOsiz, + const int Xsiz, const int Ysiz, + const int numOfreslev); + + +/** + * find deconposition level and its resolution size + * C.4.1 Mapping view-window requests to codestream image resolution + * and regions + * Note: only round-down implemented + * + * @param[in] maxlev maximum decomposition level + * @param[in/out] lev decomposition level pointer + * @param[in/out] fx horizontal frame size pointer + * @param[in/out] fy vertical frame size pointer + * @param[in/out] xmin horizontal image offset pointer + * @param[in/out] ymin vertical image offset pointer + * @param[in/out] xmax horizontal image size pointer + * @param[in/out] ymax vertical image size pointer + */ +void find_level( int maxlev, int *lev, int *fx, int *fy, int *xmin, int *ymin, int *xmax, int *ymax); + +/** + * compute decomposition level (only to get the level + * use find_level for all parameters + * + * @param[in] fx horizontal frame size + * @param[in] fy vertical frame size + * @param[in] Xsiz image width + * @param[in] Ysiz image height + * @return decomposition level + */ +int comp_decomplev( int fw, int fh, int Xsiz, int Ysiz); + +/** + * print image region parameters + * + * @param[in] imgreg image region structure of parameters + */ +void print_imgreg( imgreg_param_t imgreg); + + +#endif /* !IMGREG_MANAGER_H_ */ diff --git a/src/lib/openjpip/imgsock_manager.c b/src/lib/openjpip/imgsock_manager.c new file mode 100644 index 00000000..612cb378 --- /dev/null +++ b/src/lib/openjpip/imgsock_manager.c @@ -0,0 +1,209 @@ +/* + * $Id: imgsock_manager.c 54 2011-05-10 13:22:47Z kaori $ + * + * 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 <string.h> +#include <stdlib.h> +#include "imgsock_manager.h" +#if _WIN32 +#define strncasecmp _strnicmp +#endif + +msgtype_t identify_clientmsg( SOCKET connected_socket) +{ + OPJ_SIZE_T receive_size; + char buf[BUF_LEN]; + static const char *magicid[] = { "JPIP-stream", "PNM request", "XML request", + "TID request", "CID request", "CID destroy", "SIZ request", "JP2 save", + "QUIT"}; + int i; + + receive_size = receive_line( connected_socket, buf); + + if( receive_size == 0){ + fprintf( stderr, "Error to receive the header of client message\n"); + return MSGERROR; + } + + for( i=0; i<NUM_OF_MSGTYPES; i++){ + if( strncasecmp( magicid[i], buf, strlen(magicid[i])) == 0){ + fprintf( stderr, "%s\n", magicid[i]); + return i; + } + } + + fprintf( stderr, "Cannot identify client message type %s\n", buf); + return MSGERROR; +} + +Byte_t * receive_JPIPstream( SOCKET connected_socket, char **target, char **tid, char **cid, OPJ_SIZE_T *streamlen) +{ + char buf[BUF_LEN]; + const char versionstring[] = "version 1.2"; + int idatalen; + OPJ_SIZE_T linelen, datalen; + Byte_t *jpipstream; + + *target = *cid = *tid = NULL; + + if((linelen = receive_line( connected_socket, buf)) == 0) + return NULL; + if( strncmp( versionstring, buf, strlen(versionstring))!=0){ + fprintf( stderr, "Wrong format\n"); + return NULL; + } + + if((linelen = receive_line( connected_socket, buf)) == 0) + return NULL; + + if( strstr( buf, "jp2")){ + /* register cid option*/ + *target = strdup( buf); + + if((linelen = receive_line( connected_socket, buf)) == 0) + return NULL; + if( strcmp( buf, "0") != 0) + *tid = strdup( buf); + + if((linelen = receive_line( connected_socket, buf)) == 0) + return NULL; + if( strcmp( buf, "0") != 0) + *cid = strdup( buf); + + if((linelen = receive_line( connected_socket, buf)) == 0) + return NULL; + } + + idatalen = atoi( buf); + if( idatalen < 0 ) + { + fprintf( stderr, "Receive Data: %d Bytes\n", idatalen); + return NULL; + } + datalen = (OPJ_SIZE_T)idatalen; + fprintf( stdout, "Receive Data: %lu Bytes\n", datalen); + + jpipstream = receive_stream( connected_socket, datalen); + + /* check EOR*/ + if( jpipstream[datalen-3] == 0x00 && ( jpipstream[datalen-2] == 0x01 || jpipstream[datalen-2] == 0x02)) + *streamlen = datalen -3; + else + *streamlen = datalen; + + return jpipstream; +} + +void send_XMLstream( SOCKET connected_socket, Byte_t *xmlstream, OPJ_SIZE_T length) +{ + Byte_t header[5]; + + header[0] = 'X'; + header[1] = 'M'; + header[2] = 'L'; + header[3] = (Byte_t)((length >> 8) & 0xff); + header[4] = (Byte_t)(length & 0xff); + + send_stream( connected_socket, header, 5); + send_stream( connected_socket, xmlstream, length); +} + +void send_IDstream( SOCKET connected_socket, const char *id, OPJ_SIZE_T idlen, const char *label); + +void send_CIDstream( SOCKET connected_socket, const char *cid, OPJ_SIZE_T cidlen) +{ + send_IDstream( connected_socket, cid, cidlen, "CID"); +} + +void send_TIDstream( SOCKET connected_socket, const char *tid, OPJ_SIZE_T tidlen) +{ + send_IDstream( connected_socket, tid, tidlen, "TID"); +} + +void send_IDstream( SOCKET connected_socket, const char *id, OPJ_SIZE_T idlen, const char *label) +{ + char header[4]; + + header[0] = label[0]; + header[1] = label[1]; + header[2] = label[2]; + header[3] = (char)(idlen & 0xff); + + send_stream( connected_socket, header, 4); + send_stream( connected_socket, id, idlen); +} + +void send_PNMstream( SOCKET connected_socket, Byte_t *pnmstream, unsigned int width, unsigned int height, unsigned int numofcomp, Byte_t maxval) +{ + OPJ_SIZE_T pnmlen = 0; + Byte_t header[7]; + + pnmlen = width*height*numofcomp; + + header[0] = 'P'; + header[1] = numofcomp==3 ? 6:5; + header[2] = (width >> 8) & 0xff; + header[3] = width & 0xff; + header[4] = (height >> 8) & 0xff; + header[5] = height & 0xff; + header[6] = maxval; + + send_stream( connected_socket, header, 7); + send_stream( connected_socket, pnmstream, pnmlen); +} + +void send_SIZstream( SOCKET connected_socket, unsigned int width, unsigned int height) +{ + Byte_t responce[9]; + + responce[0] = 'S'; + responce[1] = 'I'; + responce[2] = 'Z'; + responce[3] = (width >> 16) & 0xff; + responce[4] = (width >> 8) & 0xff; + responce[5] = width & 0xff; + responce[6] = (height >> 16) & 0xff; + responce[7] = (height >> 8) & 0xff; + responce[8] = height & 0xff; + + send_stream( connected_socket, responce, 9); +} + +void response_signal( SOCKET connected_socket, bool succeed) +{ + Byte_t code; + + if( succeed) + code = 1; + else + code = 0; + + send_stream( connected_socket, &code, 1); +} diff --git a/src/lib/openjpip/imgsock_manager.h b/src/lib/openjpip/imgsock_manager.h new file mode 100644 index 00000000..044bdc53 --- /dev/null +++ b/src/lib/openjpip/imgsock_manager.h @@ -0,0 +1,174 @@ +/* + * $Id: imgsock_manager.h 54 2011-05-10 13:22:47Z kaori $ + * + * 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. + */ + +#ifndef IMGSOCK_MANAGER_H_ +# define IMGSOCK_MANAGER_H_ + +#include "bool.h" +#include "byte_manager.h" +#include "sock_manager.h" + +#define NUM_OF_MSGTYPES 9 +typedef enum eMSGTYPE{ JPIPSTREAM, PNMREQ, XMLREQ, TIDREQ, CIDREQ, CIDDST, SIZREQ, JP2SAVE, QUIT, MSGERROR} msgtype_t; + +/** + * indeitify client message type + * + * @param [in] connected_socket file descriptor of the connected socket + * @return message type + */ +msgtype_t identify_clientmsg( SOCKET connected_socket); + +/** + * receive a JPT- JPP- stream from client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [out] target address of received target file name string pointer ( malloced, if not received, NULL) + * @param [out] tid address of received target identifier string pointer ( malloced, if not received, null string) + * @param [out] cid address of received channel identifier string pointer ( malloced, if not received, null string) + * @param [out] streamlen length of the received codestream + * @return JPT- JPP- codestream + */ +Byte_t * receive_JPIPstream( SOCKET connected_socket, char **target, char **tid, char **cid, OPJ_SIZE_T *streamlen); + +/** + * send PGM/PPM image stream to the client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] pnmstream PGM/PPM image codestream + * @param [in] width width of the PGM/PPM image (different from the original image) + * @param [in] height height of the PGM/PPM image + * @param [in] numofcomp number of components of the image + * @param [in] maxval maximum value of the image (only 255 supported) + */ +void send_PNMstream( SOCKET connected_socket, Byte_t *pnmstream, unsigned int width, unsigned int height, unsigned int numofcomp, Byte_t maxval); + +/** + * send XML data stream to the client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] xmlstream xml data stream + * @param [in] length legnth of the xml data stream + */ +void send_XMLstream( SOCKET connected_socket, Byte_t *xmlstream, OPJ_SIZE_T length); + +/** + * send TID data stream to the client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] tid tid string + * @param [in] tidlen legnth of the tid string + */ +void send_TIDstream( SOCKET connected_socket, const char *tid, OPJ_SIZE_T tidlen); + +/** + * send CID data stream to the client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] cid cid string + * @param [in] cidlen legnth of the cid string + */ +void send_CIDstream( SOCKET connected_socket, const char *cid, OPJ_SIZE_T cidlen); + +/** + * send SIZ data stream to the client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] width original width of the image + * @param [in] height original height of the image + */ +void send_SIZstream( SOCKET connected_socket, unsigned int width, unsigned int height); + +/** + * send response signal to the client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] succeed whether if the requested process succeeded + */ +void response_signal( SOCKET connected_socket, bool succeed); + +#endif /* !IMGSOCK_MANAGER_H_ */ + +/*! \file + * PROTOCOL specification to communicate with opj_dec_server + * + *\section sec1 JPIP-stream + * Cache JPT- JPP- stream in server + * + * client -> server: JPIP-stream\\n version 1.1\\n (optional for cid registration: targetnamestring\\n tidstring\\n cidstring\\n) bytelengthvalue\\n data \n + * server -> client: 1 or 0 (of 1Byte response signal) + * + *\section sec2 PNM request + * Get decoded PGM/PPM image + * + * client -> server: PNM request\\n [cid/tid]string\\n fw\\n fh\\n \n + * server -> client: P6 or P5 (2Byte) width (2Byte Big endian) height (2Byte Big endian) maxval (1Byte) data + * + *\section sec3 XML request + * Get XML data + * + * client -> server: XML request\\n \n + * server -> client: XML (3Byte) length (2Byte Big endian) data + * + *\section sec4 TID request + * Get target ID of target image + * + * client -> server: TID request\\n targetname\\n \n + * server -> client: TID (3Byte) length (1Byte) tiddata + * + *\section sec5 CID request + * Get Channel ID of identical target image + * + * client -> server: CID request\\n targetname\\n \n + * server -> client: CID (3Byte) length (1Byte) ciddata + * + *\section sec6 CID destroy + * Close Channel ID + * + * client -> server: CID destroy\\n ciddata \n + * server -> client: 1 or 0 (of 1Byte response signal) + * + *\section sec7 SIZ request + * Get original size of image + * + * client -> server: SIZ request\\n tidstring\\n cidstring\\n \n + * server -> client: SIZ (3Byte) width (3Byte Big endian) height (3Byte Big endian) + * + *\section sec8 JP2 save + * Save in JP2 file format + * + * client -> server: JP2 save\\n ciddata \n + * server -> client: 1 or 0 (of 1Byte response signal) + * + *\section sec9 QUIT + * Quit the opj_dec_server program + * + * client -> server: quit or QUIT + */ diff --git a/src/lib/openjpip/index_manager.c b/src/lib/openjpip/index_manager.c new file mode 100644 index 00000000..6f8357e9 --- /dev/null +++ b/src/lib/openjpip/index_manager.c @@ -0,0 +1,732 @@ +/* + * $Id: index_manager.c 53 2011-05-09 16:55:39Z kaori $ + * + * 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 <math.h> +#include <string.h> + +#include "bool.h" +#include "opj_inttypes.h" +#include "index_manager.h" +#include "box_manager.h" +#include "manfbox_manager.h" +#include "mhixbox_manager.h" +#include "codestream_manager.h" +#include "marker_manager.h" +#include "faixbox_manager.h" +#include "boxheader_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*/ + +/** + * chekc JP2 box indexing + * + * @param[in] toplev_boxlist top level box list + * @return if correct (true) or wrong (false) + */ +bool check_JP2boxidx( boxlist_param_t *toplev_boxlist); + +/** + * set code index parameters (parse cidx box) + * Annex I + * + * @param[in] cidx_box pointer to the reference cidx_box + * @param[out] codeidx pointer to index parameters + * @return if succeeded (true) or failed (false) + */ +bool set_cidxdata( box_param_t *cidx_box, index_param_t *codeidx); + +index_param_t * parse_jp2file( int fd) +{ + index_param_t *jp2idx; + box_param_t *cidx; + metadatalist_param_t *metadatalist; + boxlist_param_t *toplev_boxlist; + Byte8_t filesize; + + if( !(filesize = (Byte8_t)get_filesize( fd))) + return NULL; + + if( !(toplev_boxlist = get_boxstructure( fd, 0, filesize))){ + fprintf( FCGI_stderr, "Error: Not correctl JP2 format\n"); + return NULL; + } + + if( !check_JP2boxidx( toplev_boxlist)){ + fprintf( FCGI_stderr, "Index format not supported\n"); + delete_boxlist( &toplev_boxlist); + return NULL; + } + + if( !(cidx = search_box( "cidx", toplev_boxlist))){ + fprintf( FCGI_stderr, "Box cidx not found\n"); + delete_boxlist( &toplev_boxlist); + return NULL; + } + + jp2idx = (index_param_t *)malloc( sizeof(index_param_t)); + + if( !set_cidxdata( cidx, jp2idx)){ + fprintf( FCGI_stderr, "Error: Not correctl format in cidx box\n"); + free(jp2idx); + delete_boxlist( &toplev_boxlist); + return NULL; + } + delete_boxlist( &toplev_boxlist); + + metadatalist = const_metadatalist( fd); + jp2idx->metadatalist = metadatalist; + +#ifndef SERVER + fprintf( logstream, "local log: code index created\n"); +#endif + + return jp2idx; +} + +void print_index( index_param_t index) +{ + int i; + + fprintf( logstream, "index info:\n"); + fprintf( logstream, "\tCodestream Offset: %#" PRIx64 "\n", index.offset); + fprintf( logstream, "\t Length: %#" PRIx64 "\n", index.length); + fprintf( logstream, "\tMain header Length: %#" PRIx64 "\n", index.mhead_length); + + print_SIZ( index.SIZ); + print_COD( index.COD); + + fprintf( logstream, "Tile part information: \n"); + print_faixbox( index.tilepart); + + fprintf( logstream, "Tile header information: \n"); + for( i=0; i<(int)(index.SIZ.XTnum*index.SIZ.YTnum);i++) + print_mhixbox( index.tileheader[i]); + + fprintf( logstream, "Precinct packet information: \n"); + for( i=0; i<index.SIZ.Csiz; i++){ + fprintf( logstream, "Component %d\n", i); + print_faixbox( index.precpacket[i]); + } + + print_allmetadata( index.metadatalist); +} + +void print_SIZ( SIZmarker_param_t SIZ) +{ + int i; + + fprintf( logstream, "\tImage and Tile SIZ parameters\n"); + fprintf( logstream, "\t Rsiz: %#x\n", SIZ.Rsiz); + fprintf( logstream, "\t Xsiz, Ysiz: (%d,%d) = (%#x, %#x)\n", SIZ.Xsiz, SIZ.Ysiz, SIZ.Xsiz, SIZ.Ysiz); + fprintf( logstream, "\t XOsiz, YOsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XOsiz, SIZ.YOsiz, SIZ.XOsiz, SIZ.YOsiz); + fprintf( logstream, "\t XTsiz, YTsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XTsiz, SIZ.YTsiz, SIZ.XTsiz, SIZ.YTsiz); + fprintf( logstream, "\t XTOsiz, YTOsiz: (%d,%d) = (%#x, %#x)\n", SIZ.XTOsiz, SIZ.YTOsiz, SIZ.XTOsiz, SIZ.YTOsiz); + fprintf( logstream, "\t XTnum, YTnum: (%d,%d)\n", SIZ.XTnum, SIZ.YTnum); + fprintf( logstream, "\t Num of Components: %d\n", SIZ.Csiz); + + for( i=0; i<SIZ.Csiz; i++) + fprintf( logstream, "\t[%d] (Ssiz, XRsiz, YRsiz): (%d, %d, %d) = (%#x, %#x, %#x)\n", i, SIZ.Ssiz[i], SIZ.XRsiz[i], SIZ.YRsiz[i], SIZ.Ssiz[i], SIZ.XRsiz[i], SIZ.YRsiz[i]); +} + +void print_COD( CODmarker_param_t COD) +{ + int i; + + fprintf( logstream, "\tCoding style default COD parameters\n"); + fprintf( logstream, "\t Progression order: %d [ LRCP=0, RLCP=1, RPCL=2, PCRL=3, CPRL=4]\n", COD.prog_order); + fprintf( logstream, "\t Num of layers: %d\n", COD.numOflayers); + fprintf( logstream, "\t Decomposition lvl: %d\n", COD.numOfdecomp); + + for( i=0; i<=((COD.Scod & 0x01) ? COD.numOfdecomp:0); i++){ + fprintf( logstream, "\t [%d] XPsiz, YPsiz: (%d,%d) = (%#x, %#x)\n",i, COD.XPsiz[i], COD.YPsiz[i], COD.XPsiz[i], COD.YPsiz[i]); + } +} + +void delete_index( index_param_t **index) +{ + int i; + + delete_metadatalist( &((*index)->metadatalist)); + + delete_COD( (*index)->COD); + + delete_faixbox( &((*index)->tilepart)); + + for( i=0; i< (int)((*index)->SIZ.XTnum*(*index)->SIZ.YTnum);i++) + delete_mhixbox( &((*index)->tileheader[i])); + free( (*index)->tileheader); + + for( i=0; i<(*index)->SIZ.Csiz; i++) + delete_faixbox( &((*index)->precpacket[i])); + free( (*index)->precpacket); + + free(*index); +} + +void delete_COD( CODmarker_param_t COD) +{ + if( COD.XPsiz) free( COD.XPsiz); + if( COD.YPsiz) free( COD.YPsiz); +} + +bool check_JP2boxidx( boxlist_param_t *toplev_boxlist) +{ + box_param_t *iptr, *fidx, *prxy; + box_param_t *cidx, *jp2c; + Byte8_t off; + Byte8_t len; + int pos; + Byte8_t ooff; + boxheader_param_t *obh; + Byte_t ni; + Byte8_t ioff; + boxheader_param_t *ibh; + + iptr = search_box( "iptr", toplev_boxlist); + fidx = search_box( "fidx", toplev_boxlist); + cidx = search_box( "cidx", toplev_boxlist); + jp2c = search_box( "jp2c", toplev_boxlist); + prxy = gene_childboxbyType( fidx, 0, "prxy"); + + off = fetch_DBox8bytebigendian( iptr, 0); + if( off != (Byte8_t)fidx->offset) + fprintf( FCGI_stderr, "Reference File Index box offset in Index Finder box not correct\n"); + + len = fetch_DBox8bytebigendian( iptr, 8); + if( len != fidx->length) + fprintf( FCGI_stderr, "Reference File Index box length in Index Finder box not correct\n"); + + pos = 0; + ooff = fetch_DBox8bytebigendian( prxy, pos); + if( ooff != (Byte8_t)jp2c->offset) + fprintf( FCGI_stderr, "Reference jp2c offset in prxy box not correct\n"); + pos += 8; + + obh = gene_childboxheader( prxy, pos); + if( obh->length != jp2c->length || strncmp( obh->type, "jp2c",4)!=0) + fprintf( FCGI_stderr, "Reference jp2c header in prxy box not correct\n"); + pos += obh->headlen; + free(obh); + + ni = fetch_DBox1byte( prxy, pos); + if( ni != 1){ + fprintf( FCGI_stderr, "Multiple indexes not supported\n"); + return false; + } + pos += 1; + + ioff = fetch_DBox8bytebigendian( prxy, pos); + if( ioff != (Byte8_t)cidx->offset) + fprintf( FCGI_stderr, "Reference cidx offset in prxy box not correct\n"); + pos += 8; + + ibh = gene_childboxheader( prxy, pos); + if( ibh->length != cidx->length || strncmp( ibh->type, "cidx",4)!=0) + fprintf( FCGI_stderr, "Reference cidx header in prxy box not correct\n"); + pos += ibh->headlen; + free(ibh); + + free(prxy); + + return true; +} + +/** + * set code index parameters from cptr box + * I.3.2.2 Codestream Finder box + * + * @param[in] cidx_box pointer to the reference cidx_box + * @param[out] jp2idx pointer to index parameters + * @return if succeeded (true) or failed (false) + */ +bool set_cptrdata( box_param_t *cidx_box, index_param_t *jp2idx); + +/** + * set code index parameters from mhix box for main header + * I.3.2.4.3 Header Index Table box + * + * @param[in] cidx_box pointer to the reference cidx_box + * @param[in] codestream codestream parameters + * @param[out] jp2idx pointer to index parameters + * @return if succeeded (true) or failed (false) + */ +bool set_mainmhixdata( box_param_t *cidx_box, codestream_param_t codestream, index_param_t *jp2idx); + +/** + * set code index parameters from tpix box + * I.3.2.4.4 Tile-part Index Table box + * + * @param[in] cidx_box pointer to the reference cidx_box + * @param[out] jp2idx pointer to index parameters + * @return if succeeded (true) or failed (false) + */ +bool set_tpixdata( box_param_t *cidx_box, index_param_t *jp2idx); + +/** + * set code index parameters from thix box + * I.3.2.4.5 Tile Header Index Table box + * + * @param[in] cidx_box pointer to the reference cidx_box + * @param[out] jp2idx pointer to index parameters + * @return if succeeded (true) or failed (false) + */ +bool set_thixdata( box_param_t *cidx_box, index_param_t *jp2idx); + +/** + * set code index parameters from ppix box + * I.3.2.4.6 Precinct Packet Index Table box + * + * @param[in] cidx_box pointer to the reference cidx_box + * @param[out] jp2idx pointer to index parameters + * @return if succeeded (true) or failed (false) + */ +bool set_ppixdata( box_param_t *cidx_box, index_param_t *jp2idx); + +bool set_cidxdata( box_param_t *cidx_box, index_param_t *jp2idx) +{ + box_param_t *manf_box; + manfbox_param_t *manf; + codestream_param_t codestream; + + set_cptrdata( cidx_box, jp2idx); + + codestream = set_codestream( cidx_box->fd, jp2idx->offset, jp2idx->length); + + manf_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "manf"); + manf = gene_manfbox( manf_box); + + if( !search_boxheader( "mhix", manf)){ + fprintf( FCGI_stderr, "Error: mhix box not present in manfbox\n"); + free(jp2idx); + return false; + } + set_mainmhixdata( cidx_box, codestream, jp2idx); + + if( !search_boxheader( "tpix", manf)){ + fprintf( FCGI_stderr, "Error: tpix box not present in manfbox\n"); + free(jp2idx); + return false; + } + set_tpixdata( cidx_box, jp2idx); + + if( !search_boxheader( "thix", manf)){ + fprintf( FCGI_stderr, "Error: thix box not present in manfbox\n"); + free(jp2idx); + return false; + } + set_thixdata( cidx_box, jp2idx); + + if( !search_boxheader( "ppix", manf)){ + fprintf( FCGI_stderr, "Error: ppix box not present in manfbox\n"); + free(jp2idx); + return false; + } + set_ppixdata( cidx_box, jp2idx); + + delete_manfbox( &manf); + free( manf_box); + + return true; +} + +bool set_cptrdata( box_param_t *cidx_box, index_param_t *jp2idx) +{ + box_param_t *box; /**< cptr box*/ + Byte2_t dr, cont; + + if( !(box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "cptr"))) + return false; + + /* DR: Data Reference. */ + /* If 0, the codestream or its Fragment Table box exists in the current file*/ + if(( dr = fetch_DBox2bytebigendian( box, 0))){ + fprintf( FCGI_stderr, "Error: Codestream not present in current file\n"); + free( box); + return false; + } + + /* CONT: Container Type*/ + /* If 0, the entire codestream appears as a contiguous range of*/ + /* bytes within its file or resource.*/ + if(( cont = fetch_DBox2bytebigendian( box, 2))){ + fprintf( FCGI_stderr, "Error: Can't cope with fragmented codestreams yet\n"); + free( box); + return false; + } + + jp2idx->offset = (OPJ_OFF_T)fetch_DBox8bytebigendian( box, 4); + jp2idx->length = fetch_DBox8bytebigendian( box, 12); + + free( box); + + return true; +} + + +/** + * set SIZ marker information + * A.5 Fixed information marker segment + * A.5.1 Image and tile size (SIZ) + * + * @param[in] sizmkidx pointer to SIZ marker index in mhix box + * @param[in] codestream codestream parameters + * @param[out] SIZ SIZ marker parameters pointer + * @return if succeeded (true) or failed (false) + */ +bool set_SIZmkrdata( markeridx_param_t *sizmkidx, codestream_param_t codestream, SIZmarker_param_t *SIZ); + +/** + * set code index parameters from COD marker in codestream + * A.6 Functional marker segments + * A.6.1 Coding style default (COD) + * + * @param[in] codmkidx pointer to COD marker index in mhix box + * @param[in] codestream codestream parameters + * @param[out] COD COD marker parameters pointer + * @return if succeeded (true) or failed (false) + */ +bool set_CODmkrdata( markeridx_param_t *codmkidx, codestream_param_t codestream, CODmarker_param_t *COD); + +bool set_mainmhixdata( box_param_t *cidx_box, codestream_param_t codestream, index_param_t *jp2idx) +{ + box_param_t *mhix_box; + mhixbox_param_t *mhix; + markeridx_param_t *sizmkidx; + markeridx_param_t *codmkidx; + + if( !(mhix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "mhix"))) + return false; + + jp2idx->mhead_length = fetch_DBox8bytebigendian( mhix_box, 0); + + mhix = gene_mhixbox( mhix_box); + free( mhix_box); + + sizmkidx = search_markeridx( 0xff51, mhix); + set_SIZmkrdata( sizmkidx, codestream, &(jp2idx->SIZ)); + + codmkidx = search_markeridx( 0xff52, mhix); + set_CODmkrdata( codmkidx, codestream, &(jp2idx->COD)); + + delete_mhixbox( &mhix); + + return true; +} + +bool set_tpixdata( box_param_t *cidx_box, index_param_t *jp2idx) +{ + box_param_t *tpix_box; /**< tpix box*/ + box_param_t *faix_box; /**< faix box*/ + + if( !(tpix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "tpix"))){ + fprintf( FCGI_stderr, "Error: tpix box not present in cidx box\n"); + return false; + } + + if( !(faix_box = gene_boxbyType( tpix_box->fd, get_DBoxoff( tpix_box), get_DBoxlen( tpix_box), "faix"))){ + fprintf( FCGI_stderr, "Error: faix box not present in tpix box\n"); + return false; + } + + jp2idx->tilepart = gene_faixbox( faix_box); + + free( tpix_box); + free( faix_box); + + return true; +} + +bool set_thixdata( box_param_t *cidx_box, index_param_t *jp2idx) +{ + box_param_t *thix_box, *manf_box, *mhix_box; + manfbox_param_t *manf; + boxheader_param_t *ptr; + mhixbox_param_t *mhix; + Byte8_t pos; + OPJ_OFF_T mhixseqoff; + Byte2_t tile_no; + + if( !(thix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "thix"))){ + fprintf( FCGI_stderr, "Error: thix box not present in cidx box\n"); + return false; + } + + if( !(manf_box = gene_boxbyType( thix_box->fd, get_DBoxoff( thix_box), get_DBoxlen( thix_box), "manf"))){ + fprintf( FCGI_stderr, "Error: manf box not present in thix box\n"); + free( thix_box); + return false; + } + + manf = gene_manfbox( manf_box); + ptr = manf->first; + mhixseqoff = manf_box->offset+(OPJ_OFF_T)manf_box->length; + pos = 0; + tile_no = 0; + jp2idx->tileheader = (mhixbox_param_t **)malloc( jp2idx->SIZ.XTnum*jp2idx->SIZ.YTnum*sizeof(mhixbox_param_t *)); + + while( ptr){ + if( !(mhix_box = gene_boxbyType( thix_box->fd, mhixseqoff+(OPJ_OFF_T)pos, get_DBoxlen( thix_box)-manf_box->length-pos, "mhix"))){ + fprintf( FCGI_stderr, "Error: mhix box not present in thix box\n"); + delete_manfbox( &manf); + free( manf_box); + free( thix_box); + return false; + } + mhix = gene_mhixbox( mhix_box); + + pos += mhix_box->length; + ptr = ptr->next; + + free( mhix_box); + jp2idx->tileheader[tile_no++] = mhix; + } + + delete_manfbox( &manf); + free( manf_box); + free( thix_box); + + return true; +} + +bool set_ppixdata( box_param_t *cidx_box, index_param_t *jp2idx) +{ + box_param_t *ppix_box, *faix_box, *manf_box; + manfbox_param_t *manf; /**< manf*/ + boxheader_param_t *bh; /**< box headers*/ + faixbox_param_t *faix; /**< faix*/ + OPJ_OFF_T inbox_offset; + int comp_idx; + + if( !(ppix_box = gene_boxbyType( cidx_box->fd, get_DBoxoff( cidx_box), get_DBoxlen( cidx_box), "ppix"))){ + fprintf( FCGI_stderr, "Error: ppix box not present in cidx box\n"); + return false; + } + + inbox_offset = get_DBoxoff( ppix_box); + if( !(manf_box = gene_boxbyType( ppix_box->fd, inbox_offset, get_DBoxlen( ppix_box), "manf"))){ + fprintf( FCGI_stderr, "Error: manf box not present in ppix box\n"); + free( ppix_box); + return false; + } + + free( ppix_box); + + manf = gene_manfbox( manf_box); + bh = search_boxheader( "faix", manf); + inbox_offset = manf_box->offset + (OPJ_OFF_T)manf_box->length; + + free( manf_box); + + jp2idx->precpacket = (faixbox_param_t **)malloc( jp2idx->SIZ.Csiz*sizeof(faixbox_param_t *)); + + for( comp_idx=0; bh!=NULL; bh=bh->next, comp_idx++){ + if( jp2idx->SIZ.Csiz <= comp_idx ){ + fprintf( FCGI_stderr, "Error: num of faix boxes is not identical to num of components in ppix box\n"); + return false; + } + + if( !(faix_box = gene_boxbyOffset( cidx_box->fd, inbox_offset))){ + fprintf( FCGI_stderr, "Error: faix box not present in ppix box\n"); + return false; + } + + faix = gene_faixbox( faix_box); + jp2idx->precpacket[comp_idx] = faix; + + inbox_offset = faix_box->offset + (OPJ_OFF_T)faix_box->length; + free( faix_box); + } + + delete_manfbox( &manf); + + return true; +} + +bool set_SIZmkrdata( markeridx_param_t *sizmkidx, codestream_param_t codestream, SIZmarker_param_t *SIZ) +{ + marker_param_t sizmkr; + int i; + + sizmkr = set_marker( codestream, sizmkidx->code, sizmkidx->offset, sizmkidx->length); + + SIZ->Lsiz = fetch_marker2bytebigendian( sizmkr, 0); + + if( sizmkidx->length != SIZ->Lsiz){ + fprintf( FCGI_stderr, "Error: marker %#x index is not correct\n", sizmkidx->code); + return false; + } + + SIZ->Rsiz = fetch_marker2bytebigendian( sizmkr, 2); + SIZ->Xsiz = fetch_marker4bytebigendian( sizmkr, 4); + SIZ->Ysiz = fetch_marker4bytebigendian( sizmkr, 8); + SIZ->XOsiz = fetch_marker4bytebigendian( sizmkr, 12); + SIZ->YOsiz = fetch_marker4bytebigendian( sizmkr, 16); + SIZ->XTsiz = fetch_marker4bytebigendian( sizmkr, 20); + SIZ->YTsiz = fetch_marker4bytebigendian( sizmkr, 24); + SIZ->XTOsiz = fetch_marker4bytebigendian( sizmkr, 28); + SIZ->YTOsiz = fetch_marker4bytebigendian( sizmkr, 32); + SIZ->Csiz = fetch_marker2bytebigendian( sizmkr, 36); + + SIZ->XTnum = ( SIZ->Xsiz-SIZ->XTOsiz+SIZ->XTsiz-1)/SIZ->XTsiz; + SIZ->YTnum = ( SIZ->Ysiz-SIZ->YTOsiz+SIZ->YTsiz-1)/SIZ->YTsiz; + + for( i=0; i<(int)SIZ->Csiz; i++){ + SIZ->Ssiz[i] = fetch_marker1byte( sizmkr, 38+i*3); + SIZ->XRsiz[i] = fetch_marker1byte( sizmkr, 39+i*3); + SIZ->YRsiz[i] = fetch_marker1byte( sizmkr, 40+i*3); + } + return true; +} + +bool set_CODmkrdata( markeridx_param_t *codmkidx, codestream_param_t codestream, CODmarker_param_t *COD) +{ + marker_param_t codmkr; + int i; + + codmkr = set_marker( codestream, codmkidx->code, codmkidx->offset, codmkidx->length); + + COD->Lcod = fetch_marker2bytebigendian( codmkr, 0); + + if( codmkidx->length != COD->Lcod){ + fprintf( FCGI_stderr, "Error: marker %#x index is not correct\n", codmkidx->code); + return false; + } + + COD->Scod = fetch_marker1byte( codmkr, 2); + COD->prog_order = fetch_marker1byte( codmkr, 3); + COD->numOflayers = fetch_marker2bytebigendian( codmkr, 4); + COD->numOfdecomp = fetch_marker1byte( codmkr, 7); + + if(COD->Scod & 0x01){ + COD->XPsiz = (Byte4_t *)malloc( (OPJ_SIZE_T)(COD->numOfdecomp+1)*sizeof(Byte4_t)); + COD->YPsiz = (Byte4_t *)malloc( (OPJ_SIZE_T)(COD->numOfdecomp+1)*sizeof(Byte4_t)); + + for( i=0; i<=COD->numOfdecomp; i++){ + /*precinct size*/ + COD->XPsiz[i] = (Byte2_t)pow( 2, fetch_marker1byte( codmkr, 12+i) & 0x0F); + COD->YPsiz[i] = (Byte2_t)pow( 2,(fetch_marker1byte( codmkr, 12+i) & 0xF0) >> 4); + } + } + else{ + COD->XPsiz = (Byte4_t *)malloc( sizeof(Byte4_t)); + COD->YPsiz = (Byte4_t *)malloc( sizeof(Byte4_t)); + + COD->XPsiz[0] = COD->YPsiz[0] = pow(2,15); + } + return true; +} + + +/* very very generic name see NOMINMAX */ +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif +Byte4_t max( Byte4_t n1, Byte4_t n2); +Byte4_t min( Byte4_t n1, Byte4_t n2); + +range_param_t get_tile_range( Byte4_t Osiz, Byte4_t siz, Byte4_t TOsiz, Byte4_t Tsiz, Byte4_t tile_XYid, int level); + +range_param_t get_tile_Xrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level) +{ + return get_tile_range( SIZ.XOsiz, SIZ.Xsiz, SIZ.XTOsiz, SIZ.XTsiz, tile_id%SIZ.XTnum, level); +} + +range_param_t get_tile_Yrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level) +{ + return get_tile_range( SIZ.YOsiz, SIZ.Ysiz, SIZ.YTOsiz, SIZ.YTsiz, tile_id/SIZ.XTnum, level); +} + +range_param_t get_tile_range( Byte4_t Osiz, Byte4_t siz, Byte4_t TOsiz, Byte4_t Tsiz, Byte4_t tile_XYid, int level) +{ + range_param_t range; + int n; + + range.minvalue = max( Osiz, TOsiz+tile_XYid*Tsiz); + range.maxvalue = min( siz, TOsiz+(tile_XYid+1)*Tsiz); + + for( n=0; n<level; n++){ + range.minvalue = (Byte4_t)ceil(range.minvalue/2.0); + range.maxvalue = (Byte4_t)ceil(range.maxvalue/2.0); + } + return range; +} + +Byte4_t get_tile_XSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level) +{ + range_param_t tile_Xrange; + + tile_Xrange = get_tile_Xrange( SIZ, tile_id, level); + return tile_Xrange.maxvalue - tile_Xrange.minvalue; +} + +Byte4_t get_tile_YSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level) +{ + range_param_t tile_Yrange; + + tile_Yrange = get_tile_Yrange( SIZ, tile_id, level); + return tile_Yrange.maxvalue - tile_Yrange.minvalue; +} + +/* TODO: what is this code doing ? will all compiler be able to optimize the following ? */ +Byte4_t max( Byte4_t n1, Byte4_t n2) +{ + if( n1 < n2) + return n2; + else + return n1; +} + +Byte4_t min( Byte4_t n1, Byte4_t n2) +{ + if( n1 < n2) + return n1; + else + return n2; +} + +bool isJPTfeasible( index_param_t index) +{ + if( 1 < get_nmax( index.tilepart)) + return true; + else + return false; +} diff --git a/src/lib/openjpip/index_manager.h b/src/lib/openjpip/index_manager.h new file mode 100644 index 00000000..c1969fac --- /dev/null +++ b/src/lib/openjpip/index_manager.h @@ -0,0 +1,187 @@ +/* + * $Id: index_manager.h 53 2011-05-09 16:55:39Z kaori $ + * + * 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. + */ + +#ifndef INDEX_MANAGER_H_ +# define INDEX_MANAGER_H_ + +#include "byte_manager.h" +#include "faixbox_manager.h" +#include "metadata_manager.h" +#include "mhixbox_manager.h" +#include "bool.h" + +/** progression order */ +typedef enum porder { + PROG_UNKNOWN = -1, /**< place-holder */ + LRCP = 0, /**< layer-resolution-component-precinct order */ + RLCP = 1, /**< resolution-layer-component-precinct order */ + RPCL = 2, /**< resolution-precinct-component-layer order */ + PCRL = 3, /**< precinct-component-resolution-layer order */ + CPRL = 4 /**< component-precinct-resolution-layer order */ +} porder_t; + +/** A.5.1 Image and tile size (SIZ)*/ +typedef struct SIZmarker_param{ + Byte2_t Lsiz; /**< length of marker segment excluding the marker*/ + Byte2_t Rsiz; /**< capabilities that a decoder needs*/ + Byte4_t Xsiz; /**< width of the reference grid*/ + Byte4_t Ysiz; /**< height of the reference grid*/ + Byte4_t XOsiz; /**< horizontal offset from the origin of the reference grid to the left side of the image area*/ + Byte4_t YOsiz; /**< vertical offset from the origin of the reference grid to the top side of the image area*/ + Byte4_t XTsiz; /**< width of one reference tile with respect to the reference grid*/ + Byte4_t YTsiz; /**< height of one reference tile with respect to the reference grid*/ + Byte4_t XTOsiz; /**< horizontal offset from the origin of the reference grid to the left side of the first tile*/ + Byte4_t YTOsiz; /**< vertical offset from the origin of the reference grid to the top side of the first tile*/ + Byte4_t XTnum; /**< number of tiles in horizontal direction*/ + Byte4_t YTnum; /**< number of tiles in vertical direction*/ + Byte2_t Csiz; /**< number of the components in the image*/ + Byte_t Ssiz[3]; /**< precision (depth) in bits and sign of the component samples*/ + Byte_t XRsiz[3]; /**< horizontal separation of a sample of component with respect to the reference grid*/ + Byte_t YRsiz[3]; /**< vertical separation of a sample of component with respect to the reference grid*/ +} SIZmarker_param_t; + +/** A.6.1 Coding style default (COD)*/ +typedef struct CODmarker_param{ + Byte2_t Lcod; /**< length of marker segment excluding the marker*/ + Byte_t Scod; /**< Coding style for all components*/ + porder_t prog_order; /**< progression order*/ + Byte2_t numOflayers; /**< number of layers*/ + Byte_t numOfdecomp; /**< number of decompositions levels*/ + Byte4_t *XPsiz; /**< dynamic array of precinct width at successive resolution level in order*/ + Byte4_t *YPsiz; /**< dynamic array of precinct height at successive resolution level in order*/ +} CODmarker_param_t; + +/** index parameters*/ +typedef struct index_param{ + metadatalist_param_t *metadatalist; /**< metadata-bin list*/ + OPJ_OFF_T offset; /**< codestream offset*/ + Byte8_t length; /**< codestream length */ + Byte8_t mhead_length; /**< main header length */ + SIZmarker_param_t SIZ; /**< SIZ marker information*/ + CODmarker_param_t COD; /**< COD marker information*/ + faixbox_param_t *tilepart; /**< tile part information from tpix box*/ + mhixbox_param_t **tileheader; /**< dynamic array of tile header information from thix box*/ + faixbox_param_t **precpacket; /**< dynamic array of precint packet information from ppix box*/ +} index_param_t; + + +/** + * parse JP2 file + * AnnexI: Indexing JPEG2000 files for JPIP + * + * @param[in] fd file descriptor of the JP2 file + * @return pointer to the generated structure of index parameters + */ +index_param_t * parse_jp2file( int fd); + +/** + * print index parameters + * + * @param[in] index index parameters + */ +void print_index( index_param_t index); + +/** + * print Image and Tile SIZ parameters + * + * @param[in] SIZ SIZ marker information + */ +void print_SIZ( SIZmarker_param_t SIZ); + +/** + * print Coding style default COD parameters + * + * @param[in] COD COD marker information + */ +void print_COD( CODmarker_param_t COD); + +/** + * delete index + * + * @param[in,out] index addressof the index pointer + */ +void delete_index( index_param_t **index); + +/** + * delete dynamic arrays in COD marker + * + * @param[in] COD COD marker information + */ +void delete_COD( CODmarker_param_t COD); + + +/** 1-dimensional range parameters*/ +typedef struct range_param{ + Byte4_t minvalue; /**< minimal value*/ + Byte4_t maxvalue; /**< maximal value*/ +} range_param_t; + +/** + * get horizontal range of the tile in reference grid + * + * @param[in] SIZ SIZ marker information + * @param[in] tile_id tile id + * @param[in] level decomposition level + * @return structured range parameter + */ +range_param_t get_tile_Xrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level); + +/** + * get vertical range of the tile in reference grid + * + * @param[in] SIZ SIZ marker information + * @param[in] tile_id tile id + * @param[in] level decomposition level + * @return structured range parameter + */ +range_param_t get_tile_Yrange( SIZmarker_param_t SIZ, Byte4_t tile_id, int level); + + +/** + * get tile wdith at the decomposition level + * + * @param[in] SIZ SIZ marker information + * @param[in] tile_id tile id + * @param[in] level decomposition level + * @return tile width + */ +Byte4_t get_tile_XSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level); +Byte4_t get_tile_YSiz( SIZmarker_param_t SIZ, Byte4_t tile_id, int level); + + +/** + * answers if the target is feasible to JPT-stream + * + * @param[in] index index parameters + * @return true if JPT-stream is feasible + */ +bool isJPTfeasible( index_param_t index); + +#endif /* !INDEX_MANAGER_H_ */ diff --git a/src/lib/openjpip/j2kheader_manager.c b/src/lib/openjpip/j2kheader_manager.c new file mode 100644 index 00000000..5a6054cc --- /dev/null +++ b/src/lib/openjpip/j2kheader_manager.c @@ -0,0 +1,295 @@ +/* + * $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 <stdlib.h> +#include <string.h> +#include <math.h> +#include <assert.h> +#include "j2kheader_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 */ + + +SIZmarker_param_t get_SIZmkrdata_from_j2kstream( Byte_t *SIZstream); +CODmarker_param_t get_CODmkrdata_from_j2kstream( Byte_t *CODstream); + +bool get_mainheader_from_j2kstream( Byte_t *j2kstream, SIZmarker_param_t *SIZ, CODmarker_param_t *COD) +{ + if( *j2kstream++ != 0xff || *j2kstream++ != 0x4f){ + fprintf( FCGI_stderr, "Error, j2kstream is not starting with SOC marker\n"); + return false; + } + + if( SIZ){ + *SIZ = get_SIZmkrdata_from_j2kstream( j2kstream); + if( SIZ->Lsiz == 0) + return false; + + j2kstream += (SIZ->Lsiz+2); + } + + if( COD){ + if( !SIZ) + j2kstream += (big2( j2kstream+2) + 2); + + *COD = get_CODmkrdata_from_j2kstream( j2kstream); + if( COD->Lcod == 0) + return false; + } + return true; +} + +SIZmarker_param_t get_SIZmkrdata_from_j2kstream( Byte_t *SIZstream) +{ + SIZmarker_param_t SIZ; + int i; + + if( *SIZstream++ != 0xff || *SIZstream++ != 0x51){ + fprintf( FCGI_stderr, "Error, SIZ marker not found in the reconstructed j2kstream\n"); + memset( &SIZ, 0, sizeof( SIZ ) ); + return SIZ; + } + + SIZ.Lsiz = big2( SIZstream); + SIZ.Rsiz = big2( SIZstream+2); + SIZ.Xsiz = big4( SIZstream+4); + SIZ.Ysiz = big4( SIZstream+8); + SIZ.XOsiz = big4( SIZstream+12); + SIZ.YOsiz = big4( SIZstream+16); + SIZ.XTsiz = big4( SIZstream+20); + SIZ.YTsiz = big4( SIZstream+24); + SIZ.XTOsiz = big4( SIZstream+28); + SIZ.YTOsiz = big4( SIZstream+32); + SIZ.Csiz = big2( SIZstream+36); + + SIZ.XTnum = ( SIZ.Xsiz-SIZ.XTOsiz+SIZ.XTsiz-1)/SIZ.XTsiz; + SIZ.YTnum = ( SIZ.Ysiz-SIZ.YTOsiz+SIZ.YTsiz-1)/SIZ.YTsiz; + + for( i=0; i<(int)SIZ.Csiz; i++){ + SIZ.Ssiz[i] = *(SIZstream+(38+i*3)); + SIZ.XRsiz[i] = *(SIZstream+(39+i*3)); + SIZ.YRsiz[i] = *(SIZstream+(40+i*3)); + } + + return SIZ; +} + +CODmarker_param_t get_CODmkrdata_from_j2kstream( Byte_t *CODstream) +{ + CODmarker_param_t COD; + int i; + + if( *CODstream++ != 0xff || *CODstream++ != 0x52){ + fprintf( FCGI_stderr, "Error, COD marker not found in the reconstructed j2kstream\n"); + return COD; + } + + COD.Lcod = big2( CODstream); + COD.Scod = *( CODstream+2); + COD.prog_order = *( CODstream+3); + COD.numOflayers = big2( CODstream+4); + COD.numOfdecomp = *( CODstream+7); + + if(COD.Scod & 0x01){ + COD.XPsiz = (Byte4_t *)malloc( (OPJ_SIZE_T)(COD.numOfdecomp+1)*sizeof(Byte4_t)); + COD.YPsiz = (Byte4_t *)malloc( (OPJ_SIZE_T)(COD.numOfdecomp+1)*sizeof(Byte4_t)); + + for( i=0; i<=COD.numOfdecomp; i++){ + /*precinct size */ + COD.XPsiz[i] = (Byte4_t)pow( 2, *( CODstream+12+i) & 0x0F); + COD.YPsiz[i] = (Byte4_t)pow( 2, (*( CODstream+12+i) & 0xF0) >> 4); + } + } + else{ + COD.XPsiz = (Byte4_t *)malloc( sizeof(Byte4_t)); + COD.YPsiz = (Byte4_t *)malloc( sizeof(Byte4_t)); + COD.XPsiz[0] = COD.YPsiz[0] = pow(2,15); + } + return COD; +} + + +bool modify_SIZmkrstream( SIZmarker_param_t SIZ, int difOfdecomplev, Byte_t *SIZstream); +Byte2_t modify_CODmkrstream( CODmarker_param_t COD, int numOfdecomp, Byte_t *CODstream); + +bool modify_mainheader( Byte_t *j2kstream, int numOfdecomp, SIZmarker_param_t SIZ, CODmarker_param_t COD, Byte8_t *j2klen) +{ + Byte2_t newLcod; + + if( *j2kstream++ != 0xff || *j2kstream++ != 0x4f){ + fprintf( FCGI_stderr, "Error, j2kstream is not starting with SOC marker\n"); + return false; + } + + if(!modify_SIZmkrstream( SIZ, COD.numOfdecomp-numOfdecomp, j2kstream)) + return false; + + j2kstream += SIZ.Lsiz+2; + if( !(newLcod = modify_CODmkrstream( COD, numOfdecomp, j2kstream))) + return false; + + memmove( j2kstream+2+newLcod, j2kstream+2+COD.Lcod, *j2klen - (Byte8_t)(SIZ.Lsiz+COD.Lcod+6)); + *j2klen -= (Byte8_t)( COD.Lcod - newLcod); + + return true; +} + +bool modify_SIZmkrstream( SIZmarker_param_t SIZ, int difOfdecomplev, Byte_t *SIZstream) +{ + int i; + + if( *SIZstream++ != 0xff || *SIZstream++ != 0x51){ + fprintf( FCGI_stderr, "Error, SIZ marker not found in the reconstructed j2kstream\n"); + return false; + } + + for( i=0; i<difOfdecomplev; i++){ + SIZ.Xsiz = (Byte4_t)ceil( (double)SIZ.Xsiz/2.0); + SIZ.Ysiz = (Byte4_t)ceil( (double)SIZ.Ysiz/2.0); + SIZ.XOsiz = (Byte4_t)ceil( (double)SIZ.XOsiz/2.0); + SIZ.YOsiz = (Byte4_t)ceil( (double)SIZ.YOsiz/2.0); + SIZ.XTsiz = (Byte4_t)ceil( (double)SIZ.XTsiz/2.0); + SIZ.YTsiz = (Byte4_t)ceil( (double)SIZ.YTsiz/2.0); + SIZ.XTOsiz = (Byte4_t)ceil( (double)SIZ.XTOsiz/2.0); + SIZ.YTOsiz = (Byte4_t)ceil( (double)SIZ.YTOsiz/2.0); + } + + SIZstream += 4; /* skip Lsiz + Rsiz */ + + modify_4Bytecode( SIZ.Xsiz, SIZstream); + modify_4Bytecode( SIZ.Ysiz, SIZstream+4); + modify_4Bytecode( SIZ.XOsiz, SIZstream+8); + modify_4Bytecode( SIZ.YOsiz, SIZstream+12); + modify_4Bytecode( SIZ.XTsiz, SIZstream+16); + modify_4Bytecode( SIZ.YTsiz, SIZstream+20); + modify_4Bytecode( SIZ.XTOsiz, SIZstream+24); + modify_4Bytecode( SIZ.YTOsiz, SIZstream+28); + + return true; +} + +Byte2_t modify_CODmkrstream( CODmarker_param_t COD, int numOfdecomp, Byte_t *CODstream) +{ + Byte2_t newLcod; + + assert( numOfdecomp >= 0 || numOfdecomp <= 255 ); + if( *CODstream++ != 0xff || *CODstream++ != 0x52){ + fprintf( FCGI_stderr, "Error, COD marker not found in the reconstructed j2kstream\n"); + return 0; + } + + if( COD.Scod & 0x01){ + newLcod = (Byte2_t)(13+numOfdecomp); + + *CODstream++ = (Byte_t)((Byte2_t)(newLcod & 0xff00) >> 8); + *CODstream++ = (Byte_t)(newLcod & 0x00ff); + } + else{ + newLcod = COD.Lcod; + CODstream += 2; + } + + CODstream += 5; /* skip Scod & SGcod */ + + /* SPcod */ + *CODstream++ = (Byte_t) numOfdecomp; + + return newLcod; +} + +bool modify_COCmkrstream( int numOfdecomp, Byte_t *COCstream, Byte2_t Csiz, Byte2_t *oldLcoc, Byte2_t *newLcoc); + +bool modify_tileheader( Byte_t *j2kstream, Byte8_t SOToffset, int numOfdecomp, Byte2_t Csiz, Byte8_t *j2klen) +{ + Byte4_t Psot; /* tile part length ref A.4.2 Start of tile-part SOT */ + Byte_t *thstream, *SOTstream, *Psot_stream; + Byte2_t oldLcoc, newLcoc; + + SOTstream = thstream = j2kstream+SOToffset; + + if( *SOTstream++ != 0xff || *SOTstream++ != 0x90){ + fprintf( FCGI_stderr, "Error, thstream is not starting with SOT marker\n"); + return false; + } + + SOTstream += 4; /* skip Lsot & Isot */ + Psot = (Byte4_t)((SOTstream[0]<<24)+(SOTstream[1]<<16)+(SOTstream[2]<<8)+(SOTstream[3])); + Psot_stream = SOTstream; + + thstream += 12; /* move to next marker (SOT always 12bytes) */ + + while( !( *thstream == 0xff && *(thstream+1) == 0x93)){ /* search SOD */ + if( numOfdecomp != -1 && *thstream == 0xff && *(thstream+1) == 0x53){ /* COC */ + if( !modify_COCmkrstream( numOfdecomp, thstream, Csiz, &oldLcoc, &newLcoc)) + return false; + + memmove( thstream+newLcoc+2, thstream+oldLcoc+2, *j2klen - (Byte8_t)(thstream-j2kstream+oldLcoc+2)); + *j2klen -= (Byte8_t)( oldLcoc - newLcoc); + } + thstream += 2; + thstream += ((thstream[0]<<8)+(thstream[1])); /* marker length */ + } + + if( (*j2klen)-SOToffset != Psot){ + Psot = (Byte4_t)((*j2klen)-SOToffset); + modify_4Bytecode( Psot, Psot_stream); + } + return true; +} + +bool modify_COCmkrstream( int numOfdecomp, Byte_t *COCstream, Byte2_t Csiz, Byte2_t *oldLcoc, Byte2_t *newLcoc) +{ + if( numOfdecomp < 0 || numOfdecomp > 255 ) return false; + if( *COCstream++ != 0xff || *COCstream++ != 0x53){ + fprintf( FCGI_stderr, "Error, COC marker not found in the reconstructed j2kstream\n"); + return false; + } + + *oldLcoc = big2( COCstream); + *newLcoc = (Byte2_t)((Csiz < 257 ? 10 : 11) + numOfdecomp); + *COCstream++ = (Byte_t)((Byte2_t)((*newLcoc) & 0xff00) >> 8); + *COCstream++ = (Byte_t)((*newLcoc) & 0x00ff); + + if( Csiz < 257) COCstream +=2; /* skip Ccoc & Scoc */ + else COCstream += 3; + + *COCstream = (Byte_t)numOfdecomp; + + return true; +} diff --git a/src/lib/openjpip/j2kheader_manager.h b/src/lib/openjpip/j2kheader_manager.h new file mode 100644 index 00000000..a6146c64 --- /dev/null +++ b/src/lib/openjpip/j2kheader_manager.h @@ -0,0 +1,73 @@ +/* + * $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 J2KHEADER_MANAGER_H_ +# define J2KHEADER_MANAGER_H_ + +#include "bool.h" +#include "byte_manager.h" +#include "index_manager.h" + +/** + * get main header information from j2k codestream + * + * @param[in] j2kstream j2k codestream + * @param[out] SIZ SIZ marker pointer + * @param[out] COD COD marker pointer + * @return if succeeded (true) or failed (false) + */ +bool get_mainheader_from_j2kstream( Byte_t *j2kstream, SIZmarker_param_t *SIZ, CODmarker_param_t *COD); + +/** + * modify main header in j2k codestream to fit with the new number of decompositions + * + * @param[in] j2kstream j2k codestream + * @param[in] numOfdecomp the New number of decompositions + * @param[in] SIZ original SIZ marker information + * @param[in] COD original COD marker information + * @param[out] j2klen pointer to the length of j2k code stream + * @return if succeeded (true) or failed (false) + */ +bool modify_mainheader( Byte_t *j2kstream, int numOfdecomp, SIZmarker_param_t SIZ, CODmarker_param_t COD, Byte8_t *j2klen); + +/** + * modify tile header in j2k codestream to fit with the tile part length, and new number of decompositions for multi-componet images + * + * @param[in] j2kstream j2k codestream + * @param[in] SOToffset offset of SOT marker from the beginning of j2kstream + * @param[in] numOfdecomp the New number of decompositions, -1 if the same as original + * @param[in] Csiz number of components + * @param[out] j2klen pointer to the length of j2k code stream + * @return if succeeded (true) or failed (false) + */ +bool modify_tileheader( Byte_t *j2kstream, Byte8_t SOToffset, int numOfdecomp, Byte2_t Csiz, Byte8_t *j2klen); + +#endif /* !J2KHEADER_MANAGER_H_ */ diff --git a/src/lib/openjpip/jp2k_decoder.c b/src/lib/openjpip/jp2k_decoder.c new file mode 100644 index 00000000..9d619b09 --- /dev/null +++ b/src/lib/openjpip/jp2k_decoder.c @@ -0,0 +1,236 @@ +/* + * $Id: jp2k_decoder.c 53 2011-05-09 16:55:39Z kaori $ + * + * 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 <string.h> +#include <stdlib.h> +#include <assert.h> +#include <limits.h> +#include "jp2k_decoder.h" +#include "openjpeg.h" + + +void error_callback(const char *msg, void *client_data); +void warning_callback(const char *msg, void *client_data); +void info_callback(const char *msg, void *client_data); + +Byte_t * imagetopnm(opj_image_t *image, ihdrbox_param_t **ihdrbox); + +Byte_t * j2k_to_pnm( FILE *fp, ihdrbox_param_t **ihdrbox) +{ + Byte_t *pnmstream = NULL; + opj_dparameters_t parameters; /* decompression parameters */ + opj_image_t *image = NULL; + opj_codec_t *l_codec = NULL; /* handle to a decompressor */ + opj_stream_t *l_stream = NULL; + + + + /* set decoding parameters to default values */ + opj_set_default_decoder_parameters(¶meters); + + /* set a byte stream */ + l_stream = opj_stream_create_default_file_stream( fp, 1); + if (!l_stream){ + fprintf(stderr, "ERROR -> failed to create the stream from the file\n"); + return NULL; + } + + /* decode the code-stream */ + /* ---------------------- */ + + /* JPEG-2000 codestream */ + /* get a decoder handle */ + l_codec = opj_create_decompress(CODEC_J2K); + + /* catch events using our callbacks and give a local context */ + opj_set_info_handler(l_codec, info_callback,00); + opj_set_warning_handler(l_codec, warning_callback,00); + opj_set_error_handler(l_codec, error_callback,00); + + /* setup the decoder decoding parameters using user parameters */ + if ( !opj_setup_decoder(l_codec, ¶meters) ){ + fprintf(stderr, "ERROR -> j2k_dump: failed to setup the decoder\n"); + return NULL; + } + + /* Read the main header of the codestream and if necessary the JP2 boxes*/ + if(! opj_read_header( l_stream, l_codec, &image)){ + fprintf(stderr, "ERROR -> j2k_to_image: failed to read the header\n"); + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(image); + return NULL; + } + +#ifdef TODO /*decode area could be set from j2k_to_pnm call, modify the protocol between JPIP viewer and opj_dec_server*/ + if (! opj_set_decode_area( l_codec, image, parameters.DA_x0, parameters.DA_y0, parameters.DA_x1, parameters.DA_y1)){ + fprintf(stderr, "ERROR -> j2k_to_image: failed to set the decoded area\n"); + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(image); + return NULL; + } +#endif /*TODO*/ + + /* Get the decoded image */ + if ( !( opj_decode(l_codec, l_stream, image) && opj_end_decompress(l_codec,l_stream) ) ) { + fprintf(stderr, "ERROR -> j2k_to_image: failed to decode image!\n"); + opj_stream_destroy(l_stream); + opj_destroy_codec(l_codec); + opj_image_destroy(image); + return NULL; + } + + fprintf(stderr, "image is decoded!\n"); + + /* close the byte stream */ + opj_stream_destroy(l_stream); + + /* create output image */ + /* ------------------- */ + if( (pnmstream = imagetopnm( image, ihdrbox))==NULL) + fprintf( stderr, "PNM image not generated\n"); + + /* free remaining structures */ + if(l_codec) { + opj_destroy_codec(l_codec); + } + + /* free image data structure */ + opj_image_destroy(image); + + return pnmstream; +} + + +/** + sample error callback expecting a FILE* client object +*/ +void error_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[ERROR] %s", msg); +} +/** + sample warning callback expecting a FILE* client object +*/ +void warning_callback(const char *msg, void *client_data) { + FILE *stream = (FILE*)client_data; + fprintf(stream, "[WARNING] %s", msg); +} +/** + sample debug callback expecting no client object +*/ +void info_callback(const char *msg, void *client_data) { + (void)client_data; + (void)msg; + /* fprintf(stdout, "[INFO] %s", msg); */ +} + + +Byte_t * imagetopnm(opj_image_t *image, ihdrbox_param_t **ihdrbox) +{ + OPJ_UINT32 adjustR, adjustG=0, adjustB=0; + OPJ_SIZE_T datasize; + Byte_t *pix=NULL, *ptr=NULL; + OPJ_UINT32 i; + + if(*ihdrbox){ + if( (*ihdrbox)->nc != image->numcomps) + fprintf( stderr, "Exception: num of components not identical, codestream: %d, ihdrbox: %d\n", image->numcomps, (*ihdrbox)->nc); + + if( (*ihdrbox)->width != image->comps[0].w) + (*ihdrbox)->width = image->comps[0].w; + + if( (*ihdrbox)->height != image->comps[0].h) + (*ihdrbox)->height = image->comps[0].h; + + if( (*ihdrbox)->bpc != image->comps[0].prec) + fprintf( stderr, "Exception: bits per component not identical, codestream: %d, ihdrbox: %d\n", image->comps[0].prec, (*ihdrbox)->bpc); + } + else{ + *ihdrbox = (ihdrbox_param_t *)malloc( sizeof(ihdrbox_param_t)); + (*ihdrbox)->width = image->comps[0].w; + (*ihdrbox)->height = image->comps[0].h; + assert( image->comps[0].prec < 256 ); + (*ihdrbox)->bpc = (Byte_t)image->comps[0].prec; + assert( image->numcomps < USHRT_MAX ); + (*ihdrbox)->nc = (Byte2_t)image->numcomps; + } + + datasize = (image->numcomps)*(image->comps[0].w)*(image->comps[0].h); + + if (image->comps[0].prec > 8) { + adjustR = image->comps[0].prec - 8; + printf("PNM CONVERSION: Truncating component 0 from %d bits to 8 bits\n", image->comps[0].prec); + } + else + adjustR = 0; + + if( image->numcomps == 3){ + if (image->comps[1].prec > 8) { + adjustG = image->comps[1].prec - 8; + printf("PNM CONVERSION: Truncating component 1 from %d bits to 8 bits\n", image->comps[1].prec); + } + else + adjustG = 0; + + if (image->comps[2].prec > 8) { + adjustB = image->comps[2].prec - 8; + printf("PNM CONVERSION: Truncating component 2 from %d bits to 8 bits\n", image->comps[2].prec); + } + else + adjustB = 0; + } + + pix = (Byte_t *)malloc( datasize); + ptr = pix; + + for( i = 0; i < image->comps[0].w * image->comps[0].h; i++){ + int r, g, b; + r = image->comps[0].data[i]; + r += (image->comps[0].sgnd ? 1 << (image->comps[0].prec - 1) : 0); + + /* if( adjustR > 0) */ + *(ptr++) = (Byte_t) ((r >> adjustR)+((r >> (adjustR-1))%2)); + + if( image->numcomps == 3){ + g = image->comps[1].data[i]; + g += (image->comps[1].sgnd ? 1 << (image->comps[1].prec - 1) : 0); + *(ptr++) = (Byte_t) ((g >> adjustG)+((g >> (adjustG-1))%2)); + + b = image->comps[2].data[i]; + b += (image->comps[2].sgnd ? 1 << (image->comps[2].prec - 1) : 0); + *(ptr++) = (Byte_t) ((b >> adjustB)+((b >> (adjustB-1))%2)); + } + } + + return pix; +} diff --git a/src/lib/openjpip/jp2k_decoder.h b/src/lib/openjpip/jp2k_decoder.h new file mode 100644 index 00000000..c999cdf1 --- /dev/null +++ b/src/lib/openjpip/jp2k_decoder.h @@ -0,0 +1,39 @@ +/* + * $Id: jp2k_decoder.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef JP2K_DECODER_H_ +# define JP2K_DECODER_H_ + +#include "byte_manager.h" +#include "ihdrbox_manager.h" + +Byte_t * j2k_to_pnm( FILE *fp, ihdrbox_param_t **ihdrbox); + +#endif /* !JP2K_DECODER_H_ */ diff --git a/src/lib/openjpip/jp2k_encoder.c b/src/lib/openjpip/jp2k_encoder.c new file mode 100644 index 00000000..23c8b2fe --- /dev/null +++ b/src/lib/openjpip/jp2k_encoder.c @@ -0,0 +1,804 @@ +/* + * $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 <stdlib.h> +#include <string.h> +#include <math.h> +#include <assert.h> +#include "jp2k_encoder.h" +#include "j2kheader_manager.h" +#include "imgreg_manager.h" +#include "opj_inttypes.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*/ + + +/** + * search a message by class_id + * + * @param[in] class_id class identifiers + * @param[in] in_class_id in-class identifiers, -1 means any + * @param[in] csn codestream number + * @param[in] msg first message pointer of the searching list + * @return found message pointer + */ +message_param_t * search_message( Byte8_t class_id, Byte8_t in_class_id, Byte8_t csn, message_param_t *msg); + +/** + * reconstruct j2k codestream from JPT- (in future, JPP-) stream + * + * @param[in] msgqueue message queue pointer + * @param[in] jpipstream original JPT- JPP- stream + * @param[in] csn codestream number + * @param[in] fw reconstructing image frame width + * @param[in] fh reconstructing image frame height + * @param[out] codelen codestream length + * @return generated reconstructed j2k codestream + */ +Byte_t * recons_codestream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *codelen); + +Byte_t * recons_j2k( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen) +{ + Byte_t *j2kstream = NULL; + + if( !msgqueue) + return NULL; + + j2kstream = recons_codestream( msgqueue, jpipstream, csn, fw, fh, j2klen); + + return j2kstream; +} + +Byte_t * add_emptyboxstream( placeholder_param_t *phld, Byte_t *jp2stream, Byte8_t *jp2len); +Byte_t * add_msgstream( message_param_t *message, Byte_t *origstream, Byte_t *j2kstream, Byte8_t *j2klen); + +Byte_t * recons_jp2( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, Byte8_t *jp2len) +{ + message_param_t *ptr; + Byte_t *jp2stream = NULL; + Byte_t *codestream = NULL; + Byte8_t codelen; + Byte8_t jp2cDBoxOffset = 0, jp2cDBoxlen = 0; + + *jp2len = 0; + + if( !msgqueue) + return NULL; + + ptr = msgqueue->first; + while(( ptr = search_message( METADATA_MSG, (Byte8_t)-1, csn, ptr))!=NULL){ + if( ptr->phld){ + if( strncmp( (char *)ptr->phld->OrigBH+4, "jp2c", 4) == 0){ + jp2cDBoxOffset = *jp2len + ptr->phld->OrigBHlen; + jp2stream = add_emptyboxstream( ptr->phld, jp2stream, jp2len); /* header only */ + jp2cDBoxlen = *jp2len - jp2cDBoxOffset; + } + else + jp2stream = add_emptyboxstream( ptr->phld, jp2stream, jp2len); /* header only */ + } + jp2stream = add_msgstream( ptr, jpipstream, jp2stream, jp2len); + ptr = ptr->next; + } + + codestream = recons_codestream( msgqueue, jpipstream, csn, 0, 0, &codelen); + + if( jp2cDBoxOffset != 0 && codelen <= jp2cDBoxlen) + memcpy( jp2stream+jp2cDBoxOffset, codestream, codelen); + + free( codestream); + + return jp2stream; +} + +bool isJPPstream( Byte8_t csn, msgqueue_param_t *msgqueue); + +Byte_t * recons_codestream_from_JPTstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, 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); + +Byte_t * add_EOC( Byte_t *j2kstream, Byte8_t *j2klen); + +Byte_t * recons_codestream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *codelen) +{ + if( isJPPstream( csn, msgqueue)) + return recons_codestream_from_JPPstream( msgqueue, jpipstream, csn, fw, fh, codelen); + else + return recons_codestream_from_JPTstream( msgqueue, jpipstream, csn, fw, fh, codelen); +} + +bool isJPPstream( Byte8_t csn, msgqueue_param_t *msgqueue) +{ + message_param_t *msg; + + msg = msgqueue->first; + while( msg){ + if( msg->csn == csn){ + if( msg->class_id <= 2) + return true; + else + if( msg->class_id == 4 || msg->class_id == 5) + return false; + } + msg = msg->next; + } + + fprintf( FCGI_stderr, "Error, message of csn %" PRId64 " not found\n", csn); + + return false; +} + +Byte_t * add_mainhead_msgstream( msgqueue_param_t *msgqueue, Byte_t *origstream, Byte_t *j2kstream, Byte8_t csn, Byte8_t *j2klen); +Byte8_t get_last_tileID( msgqueue_param_t *msgqueue, Byte8_t csn, bool isJPPstream); +Byte_t * add_emptytilestream( const Byte8_t tileID, Byte_t *j2kstream, Byte8_t *j2klen); + +Byte_t * recons_codestream_from_JPTstream( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen) +{ + Byte_t *j2kstream = NULL; + Byte8_t last_tileID, tileID; + bool found; + Byte8_t binOffset; + message_param_t *ptr; + SIZmarker_param_t SIZ; + OPJ_SIZE_T mindeclev; + + *j2klen = 0; + j2kstream = add_mainhead_msgstream( msgqueue, jpipstream, j2kstream, csn, j2klen); + + if( !get_mainheader_from_j2kstream( j2kstream, &SIZ, NULL)) + return j2kstream; + + if( fw <= 0 || fh <= 0) + mindeclev = 0; + else + mindeclev = (OPJ_SIZE_T)comp_decomplev( fw, fh, (int)SIZ.Xsiz, (int)SIZ.Ysiz); + + last_tileID = get_last_tileID( msgqueue, csn, false); + + for( tileID=0; tileID <= last_tileID; tileID++){ + found = false; + binOffset = 0; + + ptr = msgqueue->first; + while(( ptr = search_message( TILE_MSG, tileID, csn, ptr))!=NULL){ + if( ptr->bin_offset == binOffset){ + found = true; + j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen); + binOffset += ptr->length; + } + ptr = ptr->next; + } + ptr = msgqueue->first; + while(( ptr = search_message( EXT_TILE_MSG, tileID, csn, ptr))!=NULL){ + if( ptr->aux > mindeclev){ /* FIXME: pointer comparison ? */ + if( ptr->bin_offset == binOffset){ + found = true; + j2kstream = add_msgstream( ptr, jpipstream, j2kstream, j2klen); + binOffset += ptr->length; + } + } + ptr = ptr->next; + } + if(!found) + j2kstream = add_emptytilestream( tileID, j2kstream, j2klen); + } + + j2kstream = add_EOC( j2kstream, j2klen); + + return j2kstream; +} + +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) +{ + Byte_t *j2kstream = NULL; + Byte8_t tileID, last_tileID; + Byte8_t SOToffset; + bool foundTH; + Byte8_t binOffset; + message_param_t *ptr; + SIZmarker_param_t SIZ; + CODmarker_param_t COD; + int max_reslev, mindeclev; + + *j2klen = 0; + j2kstream = add_mainhead_msgstream( msgqueue, jpipstream, j2kstream, csn, j2klen); + + if( !get_mainheader_from_j2kstream( j2kstream, &SIZ, &COD)) + return j2kstream; + + if( fw == 0 || fh == 0) + mindeclev = 0; + else + mindeclev = comp_decomplev( fw, fh, (int)SIZ.Xsiz, (int)SIZ.Ysiz); + + max_reslev = -1; + last_tileID = get_last_tileID( msgqueue, csn, true); + + for( tileID=0; tileID <= last_tileID; tileID++){ + + ptr = msgqueue->first; + binOffset = 0; + foundTH = false; + 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; + } + ptr = ptr->next; + } + + if( foundTH){ + 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)){ + delete_COD( COD); + return j2kstream; + } + + j2kstream = add_EOC( j2kstream, j2klen); + delete_COD( COD); + + return j2kstream; +} + +Byte_t * add_mainhead_msgstream( msgqueue_param_t *msgqueue, Byte_t *origstream, Byte_t *j2kstream, Byte8_t csn, Byte8_t *j2klen) +{ + message_param_t *ptr; + Byte8_t binOffset; + + ptr = msgqueue->first; + binOffset = 0; + + while(( ptr = search_message( MAINHEADER_MSG, (Byte8_t)-1, csn, ptr))!=NULL){ + if( ptr->bin_offset == binOffset){ + j2kstream = add_msgstream( ptr, origstream, j2kstream, j2klen); + binOffset += ptr->length; + } + ptr = ptr->next; + } + 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 * 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; + Byte8_t seqID; + + for( r=0, seqID=0; r<=(COD.numOfdecomp-mindeclev); 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++) + 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) +{ + int ret; + Byte4_t XTsiz, YTsiz; + + XTsiz = get_tile_XSiz( SIZ, (Byte4_t)tileID, COD.numOfdecomp-r); + YTsiz = get_tile_YSiz( SIZ, (Byte4_t)tileID, COD.numOfdecomp-r); + + ret = (int)(ceil((double)XTsiz/(double)COD.XPsiz[r])*ceil((double)YTsiz/(double)COD.YPsiz[r])); + assert( ret >= 0 ); + return ret; +} + +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( (int)tileID, comp_idx, (int)seqID, (int)SIZ.Csiz, (int)SIZ.XTnum*(int)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( (int)tileID, comp_idx, (int)seqID, (int)SIZ.Csiz, (int)SIZ.XTnum*(int)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; + assert( p >= 0); + assert( r >= 0); + + for( rr=0; rr<r; rr++) + seqID += (Byte8_t)comp_numOfprcts( tileID, SIZ, COD, rr); + + seqID += (Byte8_t)p; + + return seqID; +} + +Byte8_t get_last_tileID( msgqueue_param_t *msgqueue, Byte8_t csn, bool isJPPstream) +{ + Byte8_t last_tileID = 0; + message_param_t *msg; + + msg = msgqueue->first; + while( msg){ + if( isJPPstream){ + if((msg->class_id == TILE_HEADER_MSG) && msg->csn == csn && last_tileID < msg->in_class_id) + last_tileID = msg->in_class_id; + } + else{ + if((msg->class_id == TILE_MSG || msg->class_id == EXT_TILE_MSG) && msg->csn == csn && last_tileID < msg->in_class_id) + last_tileID = msg->in_class_id; + } + msg = msg->next; + } + return last_tileID; +} + + +message_param_t * search_message( Byte8_t class_id, Byte8_t in_class_id, Byte8_t csn, message_param_t *msg) +{ + while( msg != NULL){ + if( in_class_id == (Byte8_t)-1){ + if( msg->class_id == class_id && msg->csn == csn) + return msg; + } + else{ + if( msg->class_id == class_id && msg->in_class_id == in_class_id && msg->csn == csn) + return msg; + } + msg = msg->next; + } + return NULL; +} + + +Byte_t * gene_msgstream( message_param_t *message, Byte_t *stream, Byte8_t *length); +Byte_t * gene_emptytilestream( const Byte8_t tileID, Byte8_t *length); + +Byte_t * add_msgstream( message_param_t *message, Byte_t *origstream, Byte_t *j2kstream, Byte8_t *j2klen) +{ + Byte_t *newstream; + Byte8_t newlen; + Byte_t *buf; + + if( !message) + return NULL; + + newstream = gene_msgstream( message, origstream, &newlen); + + buf = (Byte_t *)malloc(( *j2klen)+newlen); + + memcpy( buf, j2kstream, *j2klen); + memcpy( buf+(*j2klen), newstream, newlen); + + *j2klen += newlen; + + free( newstream); + if(j2kstream) free(j2kstream); + + return buf; +} + + +Byte_t * add_emptyboxstream( placeholder_param_t *phld, Byte_t *jp2stream, Byte8_t *jp2len) +{ + Byte_t *newstream; + Byte8_t newlen; + Byte_t *buf; + + if( phld->OrigBHlen == 8) + newlen = big4(phld->OrigBH); + else + newlen = big8(phld->OrigBH+8); + + newstream = (Byte_t *)malloc( newlen); + memset( newstream, 0, newlen); + memcpy( newstream, phld->OrigBH, phld->OrigBHlen); + + buf = (Byte_t *)malloc(( *jp2len)+newlen); + + memcpy( buf, jp2stream, *jp2len); + memcpy( buf+(*jp2len), newstream, newlen); + + *jp2len += newlen; + + free( newstream); + if(jp2stream) free(jp2stream); + + return buf; +} + +Byte_t * add_emptytilestream( const Byte8_t tileID, Byte_t *j2kstream, Byte8_t *j2klen) +{ + Byte_t *newstream; + Byte8_t newlen; + Byte_t *buf; + + newstream = gene_emptytilestream( tileID, &newlen); + + buf = (Byte_t *)malloc(( *j2klen)+newlen); + + memcpy( buf, j2kstream, *j2klen); + memcpy( buf+(*j2klen), newstream, newlen); + + *j2klen += newlen; + + free( newstream); + if(j2kstream) free(j2kstream); + + return buf; +} + +Byte_t * add_padding( Byte8_t padding, Byte_t *j2kstream, Byte8_t *j2klen) +{ + Byte_t *buf; + + buf = (Byte_t *)malloc(( *j2klen)+padding); + + memcpy( buf, j2kstream, *j2klen); + memset( buf+(*j2klen), 0, padding); + + *j2klen += padding; + + if(j2kstream) free(j2kstream); + + return buf; +} + +Byte_t * add_EOC( Byte_t *j2kstream, Byte8_t *j2klen) +{ + Byte2_t EOC = 0xd9ff; + + Byte_t *buf; + + buf = (Byte_t *)malloc(( *j2klen)+2); + + memcpy( buf, j2kstream, *j2klen); + memcpy( buf+(*j2klen), &EOC, 2); + + *j2klen += 2; + + if(j2kstream) free(j2kstream); + + return buf; +} + +Byte_t * gene_msgstream( message_param_t *message, Byte_t *stream, Byte8_t *length) +{ + Byte_t *buf; + + if( !message) + return NULL; + + *length = message->length; + buf = (Byte_t *)malloc( *length); + memcpy( buf, stream+message->res_offset, *length); + + return buf; +} + +Byte_t * gene_emptytilestream( const Byte8_t tileID, Byte8_t *length) +{ + Byte_t *buf; + const Byte2_t SOT = 0x90ff; + const Byte2_t Lsot = 0xa << 8; + Byte2_t Isot; + const Byte4_t Psot = 0xe << 24; + const Byte_t TPsot = 0, TNsot = 1; + const Byte2_t SOD = 0x93ff; + + *length = 14; + buf = (Byte_t *)malloc(*length); + + Isot = (Byte2_t)((((Byte2_t)tileID) << 8) | ((((Byte2_t)tileID) & 0xf0) >> 8)); + + memcpy( buf, &SOT, 2); + memcpy( buf+2, &Lsot, 2); + memcpy( buf+4, &Isot, 2); + memcpy( buf+6, &Psot, 4); + memcpy( buf+10, &TPsot, 1); + memcpy( buf+11, &TNsot, 1); + memcpy( buf+12, &SOD, 2); + + return buf; +} + +Byte_t * recons_j2kmainhead( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, Byte8_t *j2klen) +{ + *j2klen = 0; + return add_mainhead_msgstream( msgqueue, jpipstream, NULL, csn, j2klen); +} diff --git a/src/lib/openjpip/jp2k_encoder.h b/src/lib/openjpip/jp2k_encoder.h new file mode 100644 index 00000000..3945e2a0 --- /dev/null +++ b/src/lib/openjpip/jp2k_encoder.h @@ -0,0 +1,74 @@ +/* + * $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 JP2K_ENCODER_H_ +# define JP2K_ENCODER_H_ + +#include "byte_manager.h" +#include "msgqueue_manager.h" + +/** + * reconstruct j2k codestream from message queue + * + * @param[in] msgqueue message queue pointer + * @param[in] jpipstream original jpt- jpp- stream + * @param[in] csn codestream number + * @param[in] fw reconstructing image frame width + * @param[in] fh reconstructing image frame height + * @param[out] j2klen pointer to the j2k codestream length + * @return generated reconstructed j2k codestream + */ +Byte_t * recons_j2k( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, int fw, int fh, Byte8_t *j2klen); + + +/** + * reconstruct jp2 file codestream from message queue + * + * @param[in] msgqueue message queue pointer + * @param[in] jpipstream original jpt- jpp- stream + * @param[in] csn codestream number + * @param[out] jp2len pointer to the jp2 codestream length + * @return generated reconstructed jp2 codestream + */ +Byte_t * recons_jp2( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, Byte8_t *jp2len); + +/** + * reconstruct j2k codestream of mainheader from message queue + * + * @param[in] msgqueue message queue pointer + * @param[in] jpipstream original jpt- jpp- stream + * @param[in] csn codestream number + * @param[out] j2klen pointer to the j2k codestream length + * @return generated reconstructed j2k codestream + */ +Byte_t * recons_j2kmainhead( msgqueue_param_t *msgqueue, Byte_t *jpipstream, Byte8_t csn, Byte8_t *j2klen); + +#endif /* !JP2K_ENCODER_H_ */ diff --git a/src/lib/openjpip/jpip_parser.c b/src/lib/openjpip/jpip_parser.c new file mode 100644 index 00000000..663214e4 --- /dev/null +++ b/src/lib/openjpip/jpip_parser.c @@ -0,0 +1,460 @@ +/* + * $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*/ + + +bool identify_target( query_param_t query_param, targetlist_param_t *targetlist, target_param_t **target) +{ + if( query_param.tid){ + if( 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) + 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, + auxtrans_param_t auxtrans, + 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, auxtrans, 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) +{ + char *cclose; + int i; + + if( query_param.cclose[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 */ + + for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++, cclose += (strlen(cclose)+1)){ + + /* In case of the first entry of close cid */ + if( *cursession == NULL){ + if( !search_session_and_channel( cclose, sessionlist, cursession, curchannel)) + return false; + } + else /* second or more entry of close cid */ + if( !(*curchannel=search_channel( cclose, (*cursession)->channellist))){ + fprintf( FCGI_stdout, "Reason: Cclose id %s is from another session\r\n", cclose); + return false; + } + } + + /* delete channels */ + for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++, cclose += (strlen(cclose)+1)){ + *curchannel = search_channel( cclose, (*cursession)->channellist); + delete_channel( curchannel, (*cursession)->channellist); + } + + 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 + * @return if succeeded (true) or failed (false) + */ +bool 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) + if( !enqueue_metabins( query_param, codeidx->metadatalist, *msgqueue)) + return false; + + if( query_param.metadata_only) + return true; + + /* main header */ + if( !cachemodel->mhead_model && query_param.len != 0) + enqueue_mainheader( *msgqueue); + + /* image codestream */ + if( (query_param.fx > 0 && query_param.fy > 0)) + 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; + Byte4_t 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, + (int)codeidx->SIZ.XOsiz, (int)codeidx->SIZ.YOsiz, (int)codeidx->SIZ.Xsiz, (int)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 <= (Byte4_t)(imgreg.xosiz + imgreg.ox) || + tile_Xrange.minvalue >= (Byte4_t)(imgreg.xosiz + imgreg.ox + imgreg.sx) || + tile_Yrange.maxvalue <= (Byte4_t)(imgreg.yosiz + imgreg.oy) || + tile_Yrange.minvalue >= (Byte4_t)(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 >= (Byte4_t)(imgreg.xosiz + imgreg.ox) && + tile_Xrange.maxvalue <= (Byte4_t)(imgreg.xosiz + imgreg.ox + imgreg.sx) && + tile_Yrange.minvalue >= (Byte4_t)(imgreg.yosiz + imgreg.oy) && + tile_Yrange.maxvalue <= (Byte4_t)(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( (int)tile_id, msgqueue); + enqueue_allprecincts( (int)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( (int)tile_id, msgqueue); + + /* FIXME: The following code is suspicious it implicitely cast an unsigned int to int, which truncates values */ + xmin = tile_Xrange.minvalue >= (Byte4_t)(imgreg.xosiz + imgreg.ox) ? 0 : imgreg.xosiz + imgreg.ox - (int)tile_Xrange.minvalue; + xmax = tile_Xrange.maxvalue <= (Byte4_t)(imgreg.xosiz + imgreg.ox + imgreg.sx) ? (int)(tile_Xrange.maxvalue - tile_Xrange.minvalue -1) : (int)(imgreg.xosiz + imgreg.ox + imgreg.sx - (int)tile_Xrange.minvalue - 1); + ymin = tile_Yrange.minvalue >= (Byte4_t)(imgreg.yosiz + imgreg.oy) ? 0 : imgreg.yosiz + imgreg.oy - (int)tile_Yrange.minvalue; + ymax = tile_Yrange.maxvalue <= (Byte4_t)(imgreg.yosiz + imgreg.oy + imgreg.sy) ? (int)(tile_Yrange.maxvalue - tile_Yrange.minvalue - 1) : (int)(imgreg.yosiz + imgreg.oy + imgreg.sy - (int)tile_Yrange.minvalue - 1); + enqueue_precincts( xmin, xmax, ymin, ymax, (int)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; + /* MM: shouldnt xmin/xmax be Byte4_t instead ? */ + if( xmin < 0 || xmax < 0 || ymin < 0 || ymax < 0) + return; + /* MM: I think the API should not really be int should it ? */ + if( tile_id < 0 ) + return; + + 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, (Byte4_t)tile_id, dec_lev); + YTsiz = get_tile_YSiz( codeidx->SIZ, (Byte4_t)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 = (Byte4_t)u*YPsiz; + ymaxP = (Byte4_t)(u+1)*YPsiz-1; + if( YTsiz <= ymaxP) + ymaxP = YTsiz-1; + + for( v=0; v<ceil((double)XTsiz/(double)XPsiz); v++, seq_id++){ + xminP = (Byte4_t)v*XPsiz; + xmaxP = (Byte4_t)(v+1)*XPsiz-1; + if( XTsiz <= xmaxP) + xmaxP = XTsiz-1; + + if( xmaxP < (Byte4_t)xmin || xminP > (Byte4_t)xmax || ymaxP < (Byte4_t)ymin || yminP > (Byte4_t)ymax){ + /* Precinct completely excluded from view-window */ + } + else if( xminP >= (Byte4_t)xmin && xmaxP <= (Byte4_t)xmax && yminP >= (Byte4_t)ymin && ymaxP <= (Byte4_t)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; + if( tile_id < 0 ) + return; + + 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, (Byte4_t)tile_id, dec_lev); + YTsiz = get_tile_YSiz( codeidx->SIZ, (Byte4_t)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); + } + } +} + +bool 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] == '*'){ + fprintf( FCGI_stdout, "Status: 501\r\n"); + fprintf( FCGI_stdout, "Reason: metareq with all box-property * not implemented\r\n"); + return false; + } + else{ + Byte8_t idx = search_metadataidx( query_param.box_type[i], metadatalist); + + if( idx != (Byte8_t)-1) + enqueue_metadata( idx, msgqueue); + else{ + fprintf( FCGI_stdout, "Status: 400\r\n"); + fprintf( FCGI_stdout, "Reason: box-type %.4s not found\r\n", query_param.box_type[i]); + return false; + } + } + } + return true; +} diff --git a/src/lib/openjpip/jpip_parser.h b/src/lib/openjpip/jpip_parser.h new file mode 100644 index 00000000..8070c8a9 --- /dev/null +++ b/src/lib/openjpip/jpip_parser.h @@ -0,0 +1,114 @@ +/* + * $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" +#include "channel_manager.h" + +/** + * 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] auxtrans auxiliary transport + * @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, + auxtrans_param_t auxtrans, + 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); + +#endif /* !JPIP_PARSER_H_ */ diff --git a/src/lib/openjpip/jpipstream_manager.c b/src/lib/openjpip/jpipstream_manager.c new file mode 100644 index 00000000..8cb2a77f --- /dev/null +++ b/src/lib/openjpip/jpipstream_manager.c @@ -0,0 +1,120 @@ +/* + * $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 <time.h> +#include "jpipstream_manager.h" +#include "jp2k_encoder.h" +#include "jp2k_decoder.h" +#include "ihdrbox_manager.h" +#include "j2kheader_manager.h" + +Byte_t * update_JPIPstream( Byte_t *newstream, OPJ_SIZE_T newstreamlen, Byte_t *cache_stream, OPJ_SIZE_T *streamlen) +{ + Byte_t *stream = (Byte_t *)malloc( (*streamlen)+newstreamlen); + if( *streamlen > 0) + memcpy( stream, cache_stream, *streamlen); + memcpy( stream+(*streamlen), newstream, newstreamlen); + *streamlen += newstreamlen; + + if(cache_stream) + free( cache_stream); + + return stream; +} + +void save_codestream( Byte_t *codestream, OPJ_SIZE_T streamlen, const char *fmt) +{ + time_t timer; + struct tm *t_st; + char filename[20]; + FILE *fp; + + time(&timer); + t_st = localtime( &timer); + + sprintf( filename, "%4d%02d%02d%02d%02d%02d.%.3s", t_st->tm_year+1900, t_st->tm_mon+1, t_st->tm_mday, t_st->tm_hour, t_st->tm_min, t_st->tm_sec, fmt); + + fp = fopen( filename, "wb"); + if( fwrite( codestream, streamlen, 1, fp) != 1) + fprintf( stderr, "Error: failed to write codestream to file %s\n", filename); + fclose( fp); +} + + +Byte_t * jpipstream_to_pnm( Byte_t *jpipstream, msgqueue_param_t *msgqueue, Byte8_t csn, int fw, int fh, ihdrbox_param_t **ihdrbox) +{ + Byte_t *pnmstream; + Byte_t *j2kstream; /* j2k or jp2 codestream */ + Byte8_t j2klen; + FILE *fp; + const char j2kfname[] = "tmp.j2k"; + + j2kstream = recons_j2k( msgqueue, jpipstream, csn, fw, fh, &j2klen); + + fp = fopen( j2kfname, "w+b"); + fwrite( j2kstream, j2klen, 1, fp); + free( j2kstream); + fseek( fp, 0, SEEK_SET); + + pnmstream = j2k_to_pnm( fp, ihdrbox); + + fclose( fp); + remove( j2kfname); + + return pnmstream; +} + +ihdrbox_param_t * get_SIZ_from_jpipstream( Byte_t *jpipstream, msgqueue_param_t *msgqueue, Byte8_t csn) +{ + ihdrbox_param_t *ihdrbox; + Byte_t *j2kstream; + Byte8_t j2klen; + SIZmarker_param_t SIZ; + + j2kstream = recons_j2kmainhead( msgqueue, jpipstream, csn, &j2klen); + if( !get_mainheader_from_j2kstream( j2kstream, &SIZ, NULL)){ + free( j2kstream); + return NULL; + } + + ihdrbox = (ihdrbox_param_t *)malloc( sizeof(ihdrbox_param_t)); + + ihdrbox->width = SIZ.Xsiz; + ihdrbox->height = SIZ.Ysiz; + ihdrbox->nc = SIZ.Csiz; + ihdrbox->bpc = SIZ.Ssiz[0]; + + free( j2kstream); + + return ihdrbox; +} diff --git a/src/lib/openjpip/jpipstream_manager.h b/src/lib/openjpip/jpipstream_manager.h new file mode 100644 index 00000000..5328be62 --- /dev/null +++ b/src/lib/openjpip/jpipstream_manager.h @@ -0,0 +1,41 @@ +/* + * $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 "byte_manager.h" +#include "msgqueue_manager.h" +#include "ihdrbox_manager.h" + +Byte_t * update_JPIPstream( Byte_t *newstream, OPJ_SIZE_T newstreamlen, Byte_t *cache_stream, OPJ_SIZE_T *streamlen); + +void save_codestream( Byte_t *codestream, OPJ_SIZE_T streamlen, const char *fmt); + +Byte_t * jpipstream_to_pnm( Byte_t *jpipstream, msgqueue_param_t *msgqueue, Byte8_t csn, int fw, int fh, ihdrbox_param_t **ihdrbox); + +ihdrbox_param_t * get_SIZ_from_jpipstream( Byte_t *jpipstream, msgqueue_param_t *msgqueue, Byte8_t csn); diff --git a/src/lib/openjpip/manfbox_manager.c b/src/lib/openjpip/manfbox_manager.c new file mode 100644 index 00000000..37472461 --- /dev/null +++ b/src/lib/openjpip/manfbox_manager.c @@ -0,0 +1,115 @@ +/* + * $Id: manfbox_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "manfbox_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 */ + +manfbox_param_t * gene_manfbox( box_param_t *box) +{ + manfbox_param_t *manf; /* manifest parameters */ + boxheader_param_t *bh; /* current box pointer */ + boxheader_param_t *last; /* last boxheader pointer of the list */ + OPJ_OFF_T pos; /* current position in manf_box contents; */ + + manf = ( manfbox_param_t *)malloc( sizeof( manfbox_param_t)); + + pos = 0; + manf->first = last = NULL; + + while( (OPJ_SIZE_T)pos < get_DBoxlen( box)){ + + bh = gene_childboxheader( box, pos); + pos += bh->headlen; + + /* insert into the list */ + if( manf->first) + last->next = bh; + else + manf->first = bh; + last = bh; + } + return manf; +} + +void delete_manfbox( manfbox_param_t **manf) +{ + boxheader_param_t *bhPtr, *bhNext; + + bhPtr = (*manf)->first; + while( bhPtr != NULL){ + bhNext = bhPtr->next; +#ifndef SERVER + /* fprintf( logstream, "local log: boxheader %.4s deleted!\n", bhPtr->type); */ +#endif + free(bhPtr); + bhPtr = bhNext; + } + free( *manf); +} + +void print_manfbox( manfbox_param_t *manf) +{ + boxheader_param_t *ptr; + + ptr = manf->first; + while( ptr != NULL){ + print_boxheader( ptr); + ptr=ptr->next; + } +} + +boxheader_param_t * search_boxheader( const char type[], manfbox_param_t *manf) +{ + boxheader_param_t *found; + + found = manf->first; + + while( found != NULL){ + + if( strncmp( type, found->type, 4) == 0) + return found; + + found = found->next; + } + fprintf( FCGI_stderr, "Error: Boxheader %s not found\n", type); + + return NULL; +} diff --git a/src/lib/openjpip/manfbox_manager.h b/src/lib/openjpip/manfbox_manager.h new file mode 100644 index 00000000..ed4189e0 --- /dev/null +++ b/src/lib/openjpip/manfbox_manager.h @@ -0,0 +1,81 @@ +/* + * $Id: manfbox_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef MANFBOX_MANAGER_H_ +# define MANFBOX_MANAGER_H_ + +#include "byte_manager.h" +#include "box_manager.h" +#include "boxheader_manager.h" + + +/** manifest box parameters*/ +/** I.3.2.3 Manifest box*/ +typedef struct manfbox_param{ + boxheader_param_t *first; /**< top of the box header list*/ +} manfbox_param_t; + + +/** + * generate manifest box + * + * @param[in] box pointer to the reference manf box + * @return generated manfbox + */ +manfbox_param_t * gene_manfbox( box_param_t *box); + + +/** + * delete manifest box + * + * @param[in,out] manf addressof the manfbox pointer + */ +void delete_manfbox( manfbox_param_t **manf); + + +/** + * print manf box parameters + * + * @param[in] manf manf box pointer + */ +void print_manfbox( manfbox_param_t *manf); + + +/** + * search a boxheader by box type from manifest box + * + * @param[in] type box type + * @param[in] manf manf box pointer + * @return found box pointer + */ +boxheader_param_t * search_boxheader( const char type[], manfbox_param_t *manf); + + +#endif /* !MANFBOX_MANAGER_H_ */ diff --git a/src/lib/openjpip/marker_manager.c b/src/lib/openjpip/marker_manager.c new file mode 100644 index 00000000..766ecd6e --- /dev/null +++ b/src/lib/openjpip/marker_manager.c @@ -0,0 +1,68 @@ +/* + * $Id: marker_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 "marker_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 */ + +marker_param_t set_marker( codestream_param_t cs, Byte2_t code, OPJ_OFF_T offset, Byte2_t length) +{ + marker_param_t mkr; + + mkr.cs = cs; + mkr.code = code; + mkr.offset = offset; + mkr.length = length; + + return mkr; +} + + +Byte_t fetch_marker1byte( marker_param_t marker, OPJ_OFF_T offset) +{ + return fetch_codestream1byte( &(marker.cs), marker.offset+offset); +} + +Byte2_t fetch_marker2bytebigendian( marker_param_t marker, OPJ_OFF_T offset) +{ + return fetch_codestream2bytebigendian( &(marker.cs), marker.offset+offset); +} + +Byte4_t fetch_marker4bytebigendian( marker_param_t marker, OPJ_OFF_T offset) +{ + return fetch_codestream4bytebigendian( &(marker.cs), marker.offset+offset); +} diff --git a/src/lib/openjpip/marker_manager.h b/src/lib/openjpip/marker_manager.h new file mode 100644 index 00000000..68ea2a8b --- /dev/null +++ b/src/lib/openjpip/marker_manager.h @@ -0,0 +1,87 @@ +/* + * $Id: marker_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef MARKER_MANAGER_H_ +# define MARKER_MANAGER_H_ + +#include "codestream_manager.h" + + +/** Marker parameters*/ +typedef struct marker_param{ + codestream_param_t cs; /**< corresponding codestream*/ + Byte2_t code; /**< marker code*/ + OPJ_OFF_T offset; /**< offset relative to the start of the codestream ( including the length parameter but not the marker itself)*/ + Byte2_t length; /**< marker segment length*/ +} marker_param_t; + + +/** + * set marker parameters from inputs + * + * @param[in] cs marker code + * @param[in] code marker code + * @param[in] offset offset in the codestream + * @param[in] length marker segment length + * @return structure of generated marker parameters + */ +marker_param_t set_marker( codestream_param_t cs, Byte2_t code, OPJ_OFF_T offset, Byte2_t length); + + +/** + * fetch marker content 1-bytes of data in file stream + * + * @param[in] marker marker structure + * @param[in] offset start Byte position in marker + * @param[in] size Byte length + * @return fetched code + */ +Byte_t fetch_marker1byte( marker_param_t marker, OPJ_OFF_T offset); + +/** + * fetch marker content 2-byte big endian Byte codes in file stream + * + * @param[in] marker marker structure + * @param[in] offset start Byte position in marker + * @return fetched code + */ +Byte2_t fetch_marker2bytebigendian( marker_param_t marker, OPJ_OFF_T offset); + +/** + * fetch marker content 4-byte big endian Byte codes in file stream + * + * @param[in] marker marker structure + * @param[in] offset start Byte position in marker + * @return fetched code + */ +Byte4_t fetch_marker4bytebigendian( marker_param_t marker, OPJ_OFF_T offset); + + +#endif /* !MARKER_MANAGER_H_ */ diff --git a/src/lib/openjpip/metadata_manager.c b/src/lib/openjpip/metadata_manager.c new file mode 100644 index 00000000..12b61efc --- /dev/null +++ b/src/lib/openjpip/metadata_manager.c @@ -0,0 +1,253 @@ +/* + * $Id: metadata_manager.c 53 2011-05-09 16:55:39Z kaori $ + * + * 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 "metadata_manager.h" +#include "opj_inttypes.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <assert.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*/ + + +metadatalist_param_t * gene_metadatalist(void) +{ + metadatalist_param_t *list; + + list = (metadatalist_param_t *)malloc( sizeof(metadatalist_param_t)); + + list->first = NULL; + list->last = NULL; + + return list; +} + +metadatalist_param_t * const_metadatalist( int fd) +{ + metadatalist_param_t *metadatalist; + metadata_param_t *metabin; + boxlist_param_t *toplev_boxlist; + box_param_t *box, *next; + placeholderlist_param_t *phldlist; + placeholder_param_t *phld; + Byte8_t idx; + Byte8_t filesize; + + if(!(filesize = (Byte8_t)get_filesize( fd))) + return NULL; + + if( !(toplev_boxlist = get_boxstructure( fd, 0, filesize))){ + fprintf( FCGI_stderr, "Error: Not correctl JP2 format\n"); + return NULL; + } + + phldlist = gene_placeholderlist(); + metadatalist = gene_metadatalist(); + + box = toplev_boxlist->first; + idx = 0; + while( box){ + next = box->next; + if( strncmp( box->type, "jP ",4)!=0 && strncmp( box->type, "ftyp",4)!=0 && strncmp( box->type, "jp2h",4)!=0){ + boxlist_param_t *boxlist = NULL; + boxcontents_param_t *boxcontents = NULL; + + phld = gene_placeholder( box, ++idx); + insert_placeholder_into_list( phld, phldlist); + + boxlist = get_boxstructure( box->fd, get_DBoxoff( box), get_DBoxlen(box)); + if( !boxlist) + boxcontents = gene_boxcontents( get_DBoxoff( box), get_DBoxlen(box)); + + delete_box_in_list( &box, toplev_boxlist); + metabin = gene_metadata( idx, boxlist, NULL, boxcontents); + insert_metadata_into_list( metabin, metadatalist); + } + box = next; + } + + metabin = gene_metadata( 0, toplev_boxlist, phldlist, NULL); + insert_metadata_into_list( metabin, metadatalist); + + return metadatalist; +} + +void delete_metadatalist( metadatalist_param_t **list) +{ + metadata_param_t *ptr, *next; + + ptr = (*list)->first; + + while( ptr != NULL){ + next=ptr->next; + delete_metadata( &ptr); + ptr=next; + } + free( *list); +} + +metadata_param_t * gene_metadata( Byte8_t idx, boxlist_param_t *boxlist, placeholderlist_param_t *phldlist, boxcontents_param_t *boxcontents) +{ + metadata_param_t *bin; + + bin = (metadata_param_t *)malloc( sizeof(metadata_param_t)); + bin->idx = idx; + bin->boxlist = boxlist; + bin->placeholderlist = phldlist; + bin->boxcontents = boxcontents; + bin->next = NULL; + + return bin; +} + +void delete_metadata( metadata_param_t **metadata) +{ + delete_boxlist( &((*metadata)->boxlist)); + delete_placeholderlist( &((*metadata)->placeholderlist)); + if((*metadata)->boxcontents) + free((*metadata)->boxcontents); +#ifndef SERVER + /* fprintf( logstream, "local log: Metadata-bin: %d deleted\n", (*metadata)->idx);*/ +#endif + free( *metadata); +} + +void insert_metadata_into_list( metadata_param_t *metabin, metadatalist_param_t *metadatalist) +{ + if( metadatalist->first) + metadatalist->last->next = metabin; + else + metadatalist->first = metabin; + metadatalist->last = metabin; +} + +void print_metadata( metadata_param_t *metadata) +{ + boxcontents_param_t *boxcont; + fprintf( logstream, "metadata-bin %" PRIu64 " info:\n", metadata->idx); + print_allbox( metadata->boxlist); + print_allplaceholder( metadata->placeholderlist); + + boxcont = metadata->boxcontents; + if( boxcont) + fprintf( logstream, "box contents:\n" + "\t offset: %" PRId64 " %#" PRIx64 "\n" + "\t length: %" PRId64 " %#" PRIx64 "\n", boxcont->offset, + boxcont->offset, boxcont->length, boxcont->length); +} + +void print_allmetadata( metadatalist_param_t *list) +{ + metadata_param_t *ptr; + + fprintf( logstream, "all metadata info: \n"); + ptr = list->first; + while( ptr != NULL){ + print_metadata( ptr); + ptr=ptr->next; + } +} + +boxcontents_param_t * gene_boxcontents( OPJ_OFF_T offset, OPJ_SIZE_T length) +{ + boxcontents_param_t *contents; + + contents = (boxcontents_param_t *)malloc( sizeof(boxcontents_param_t)); + + contents->offset = offset; + contents->length = length; + + return contents; +} + +metadata_param_t * search_metadata( Byte8_t idx, metadatalist_param_t *list) +{ + metadata_param_t *found; + + found = list->first; + + while( found){ + + if( found->idx == idx) + return found; + + found = found->next; + } + return NULL; +} + +Byte8_t search_metadataidx( char boxtype[4], metadatalist_param_t *list) +{ + /* MM FIXME: what is the return type of this function ? + Byte8_t or int ? */ + metadata_param_t *ptr; + int i; + + for( i=0; i<4; i++) + if( boxtype[i] == '_') + boxtype[i] = ' '; + + ptr = list->first; + while( ptr){ + if( ptr->boxlist){ + box_param_t *box = ptr->boxlist->first; + while( box){ + if( strncmp ( boxtype, box->type, 4) == 0) + return ptr->idx; + box = box->next; + } + } + ptr = ptr->next; + } + + ptr = list->first; + while( ptr){ + if( ptr->placeholderlist){ + placeholder_param_t *phld = ptr->placeholderlist->first; + while( phld){ + if( strncmp ( boxtype, (char *)phld->OrigBH+4, 4) == 0){ + return phld->OrigID; + } + phld = phld->next; + } + } + ptr = ptr->next; + } + return (Byte8_t)-1; +} diff --git a/src/lib/openjpip/metadata_manager.h b/src/lib/openjpip/metadata_manager.h new file mode 100644 index 00000000..089b19a5 --- /dev/null +++ b/src/lib/openjpip/metadata_manager.h @@ -0,0 +1,151 @@ +/* + * $Id: metadata_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef METADATA_MANAGER_H_ +#define METADATA_MANAGER_H_ + +#include "box_manager.h" +#include "placeholder_manager.h" + +typedef struct boxcontents_param{ + OPJ_OFF_T offset; /**< byte position of the box contents in the file*/ + Byte8_t length; /**< length of the box contents*/ +} boxcontents_param_t; + +/** metadata-bin parameters*/ +typedef struct metadata_param{ + Byte8_t idx; /**< index number*/ + boxlist_param_t *boxlist; /**< box list*/ + placeholderlist_param_t *placeholderlist; /**< placeholder box list*/ + boxcontents_param_t *boxcontents; /**< box contens in case of no boxlist and placeholderlist*/ + struct metadata_param *next; /**< pointer to the next metadata-bin*/ +} metadata_param_t; + +/** metadata-bin list parameters*/ +typedef struct metadatalist_param{ + metadata_param_t *first; /**< first metadata-bin pointer of the list*/ + metadata_param_t *last; /**< last metadata-bin pointer of the list*/ +} metadatalist_param_t; + + +/** + * generate a metadata list + * + * @return pointer to the generated metadata list + */ +metadatalist_param_t * gene_metadatalist(void); + + +/** + * construct metadata-bin list of JP2 file + * + * @param[in] fd file descriptor + * @return pointer to the generated metadata-bin list + */ +metadatalist_param_t * const_metadatalist( int fd); + + +/** + * delete metadata list + * + * @param[in,out] list address of the metadata list pointer + */ +void delete_metadatalist( metadatalist_param_t **list); + + +/** + * generate a metadata bin + * + * @param[in] idx metadata-bin index + * @param[in] boxlist box list pointer + * @param[in] phldlist placeholder list pointer + * @param[in] boxcontents boxcontents pointer + * @return pointer to the generated metadata bin + */ +metadata_param_t * gene_metadata( Byte8_t idx, boxlist_param_t *boxlist, placeholderlist_param_t *phldlist, boxcontents_param_t *boxcontents); + +/** + * delete a metadata bin + * + * @param[in,out] metadata address of the deleting metadata bin pointer + */ +void delete_metadata( metadata_param_t **metadata); + +/** + * generate box contents + * + * @return pointer to the box contents + */ +boxcontents_param_t * gene_boxcontents( OPJ_OFF_T offset, OPJ_SIZE_T length); + +/** + * print metadata-bin parameters + * + * @param[in] metadata metadata-bin pointer + */ +void print_metadata( metadata_param_t *metadata); + +/** + * print all metadata parameters + * + * @param[in] metadatalist metadata list pointer + */ +void print_allmetadata( metadatalist_param_t *list); + + +/** + * search a metadata bin by index + * + * @param[in] idx index + * @param[in] list metadata-bin list pointer + * @return found metadata-bin pointer + */ +metadata_param_t * search_metadata( Byte8_t idx, metadatalist_param_t *list); + + +/** + * search a metadata index by box-type + * + * @param[in] boxtype box-type + * @param[in] list metadata-bin list pointer + * @return found metadata-bin index, if not found, -1 + */ +Byte8_t search_metadataidx( char boxtype[4], metadatalist_param_t *list); + + +/** + * insert a metadata-bin into list + * + * @param[in] metabin metadata-bin pointer + * @param[in] metadatalist metadata list pointer + */ +void insert_metadata_into_list( metadata_param_t *metabin, metadatalist_param_t *metadatalist); + +#endif /* !METADATA_MANAGER_H_ */ diff --git a/src/lib/openjpip/mhixbox_manager.c b/src/lib/openjpip/mhixbox_manager.c new file mode 100644 index 00000000..b311126b --- /dev/null +++ b/src/lib/openjpip/mhixbox_manager.c @@ -0,0 +1,141 @@ +/* + * $Id: mhixbox_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 "mhixbox_manager.h" +#include "opj_inttypes.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 */ + + +mhixbox_param_t * gene_mhixbox( box_param_t *box) +{ + mhixbox_param_t *mhix; + markeridx_param_t *mkridx, *lastmkidx; + OPJ_OFF_T pos = 0; + + mhix = ( mhixbox_param_t *)malloc( sizeof( mhixbox_param_t)); + + mhix->tlen = fetch_DBox8bytebigendian( box, (pos+=8)-8); + + mhix->first = lastmkidx = NULL; + while( (OPJ_SIZE_T)pos < get_DBoxlen( box)){ + + mkridx = ( markeridx_param_t *)malloc( sizeof( markeridx_param_t)); + mkridx->code = fetch_DBox2bytebigendian( box, (pos+=2)-2); + mkridx->num_remain = fetch_DBox2bytebigendian( box, (pos+=2)-2); + mkridx->offset = (OPJ_OFF_T)fetch_DBox8bytebigendian( box, (pos+=8)-8); + mkridx->length = fetch_DBox2bytebigendian( box, (pos+=2)-2); + mkridx->next = NULL; + + if( mhix->first) + lastmkidx->next = mkridx; + else + mhix->first = mkridx; + lastmkidx = mkridx; + } + return mhix; +} + + +markeridx_param_t * search_markeridx( Byte2_t code, mhixbox_param_t *mhix) +{ + markeridx_param_t *found; + + found = mhix->first; + + while( found != NULL){ + + if( code == found->code) + return found; + + found = found->next; + } + fprintf( FCGI_stderr, "Error: Marker index %#x not found\n", code); + + return NULL; +} + + +void print_mhixbox( mhixbox_param_t *mhix) +{ + markeridx_param_t *ptr; + + fprintf( logstream, "mhix box info:\n"); + fprintf( logstream, "\t tlen: %#" PRIx64 "\n", mhix->tlen); + + ptr = mhix->first; + while( ptr != NULL){ + fprintf( logstream, "marker index info:\n" + "\t code: %#x\n" + "\t num_remain: %#x\n" + "\t offset: %#" PRIx64 "\n" + "\t length: %#x\n", ptr->code, ptr->num_remain, ptr->offset, ptr->length); + ptr=ptr->next; + } +} + + +void print_markeridx( markeridx_param_t *markeridx) +{ + fprintf( logstream, "marker index info:\n" + "\t code: %#x\n" + "\t num_remain: %#x\n" + "\t offset: %#" PRIx64 "\n" + "\t length: %#x\n", markeridx->code, markeridx->num_remain, markeridx->offset, markeridx->length); +} + + +void delete_mhixbox( mhixbox_param_t **mhix) +{ + markeridx_param_t *mkPtr, *mkNext; + + mkPtr = (*mhix)->first; + while( mkPtr != NULL){ + mkNext=mkPtr->next; +#ifndef SERVER + /* fprintf( logstream, "local log: marker index %#x deleted!\n", mkPtr->code); */ +#endif + free(mkPtr); + mkPtr=mkNext; + } + free(*mhix); +} + + diff --git a/src/lib/openjpip/mhixbox_manager.h b/src/lib/openjpip/mhixbox_manager.h new file mode 100644 index 00000000..5905b25f --- /dev/null +++ b/src/lib/openjpip/mhixbox_manager.h @@ -0,0 +1,102 @@ +/* + * $Id: mhixbox_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef MHIXBOX_MANAGER_H_ +# define MHIXBOX_MANAGER_H_ + +#include "byte_manager.h" +#include "box_manager.h" + +/** Marker index parameters*/ +typedef struct markeridx_param{ + Byte2_t code; /**< marker code*/ + Byte2_t num_remain; /**< remining number of the same marker index segments listed immediately*/ + OPJ_OFF_T offset; /**< offset relative to the start of the*/ + /**codestream ( including the length*/ + /**parameter but not the marker itself)*/ + Byte2_t length; /**< marker segment length*/ + struct markeridx_param *next; /**< pointer to the next markeridx*/ +} markeridx_param_t; + + + +/** header index table box parameters*/ +/** I.3.2.4.3 Header Index Table box*/ +typedef struct mhixbox_param{ + Byte8_t tlen; /**< length ( total length of the main*/ + /**header or of the first tile-part header)*/ + markeridx_param_t *first; /**< first marker index pointer of the list*/ +} mhixbox_param_t; + + + +/** + * generate mhix box + * + * @param[in] box pointer to the reference mhix box + * @return generated mhixbox pointer + */ +mhixbox_param_t * gene_mhixbox( box_param_t *box); + + +/** + * search a marker index by marker code from mhix box + * + * @param[in] code marker code + * @param[in] mhix mhix box pointer + * @return found marker index pointer + */ +markeridx_param_t * search_markeridx( Byte2_t code, mhixbox_param_t *mhix); + + +/** + * print mhix box parameters + * + * @param[in] mhix mhix box pointer + */ +void print_mhixbox( mhixbox_param_t *mhix); + + +/** + * print marker index parameters + * + * @param[in] markeridx marker index pointer + */ +void print_markeridx( markeridx_param_t *markeridx); + + +/** + * delete mhix box + * + * @param[in,out] mhix address of the mhix box pointer + */ +void delete_mhixbox( mhixbox_param_t **mhix); + +#endif /* !MHIXBOX_MANAGER_H_ */ diff --git a/src/lib/openjpip/msgqueue_manager.c b/src/lib/openjpip/msgqueue_manager.c new file mode 100644 index 00000000..29b64a26 --- /dev/null +++ b/src/lib/openjpip/msgqueue_manager.c @@ -0,0 +1,762 @@ +/* + * $Id: msgqueue_manager.c 53 2011-05-09 16:55:39Z kaori $ + * + * 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 <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#include <limits.h> +#ifdef _WIN32 +#include <io.h> +#else +#include <unistd.h> +#endif +#include "msgqueue_manager.h" +#include "metadata_manager.h" +#include "index_manager.h" +#include "opj_inttypes.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*/ + +msgqueue_param_t * gene_msgqueue( bool stateless, cachemodel_param_t *cachemodel) +{ + msgqueue_param_t *msgqueue; + + msgqueue = (msgqueue_param_t *)malloc( sizeof(msgqueue_param_t)); + + msgqueue->first = NULL; + msgqueue->last = NULL; + + msgqueue->stateless = stateless; + msgqueue->cachemodel = cachemodel; + + return msgqueue; +} + +void delete_msgqueue( msgqueue_param_t **msgqueue) +{ + message_param_t *ptr, *next; + + if( !(*msgqueue)) + return; + + ptr = (*msgqueue)->first; + + while( ptr){ + next = ptr->next; + free( ptr); + ptr = next; + } + if( (*msgqueue)->stateless && (*msgqueue)->cachemodel) + delete_cachemodel( &((*msgqueue)->cachemodel)); + + free(*msgqueue); +} + +void print_msgqueue( msgqueue_param_t *msgqueue) +{ + message_param_t *ptr; + static const char *message_class[] = { "Precinct", "Ext-Prec", "TileHead", "non", + "Tile", "Ext-Tile", "Main", "non", "Meta"}; + + if( !msgqueue) + return; + + fprintf( logstream, "message queue:\n"); + ptr = msgqueue->first; + + while( ptr){ + fprintf( logstream, "\t class_id: %" PRId64 " %s\n", ptr->class_id, message_class[ptr->class_id]); + fprintf( logstream, "\t in_class_id: %" PRId64 "\n", ptr->in_class_id ); + fprintf( logstream, "\t csn: %" PRId64 "\n", ptr->csn ); + fprintf( logstream, "\t bin_offset: %#" PRIx64 "\n", ptr->bin_offset ); + fprintf( logstream, "\t length: %#" PRIx64 "\n", ptr->length ); + if( ptr->class_id%2) + fprintf( logstream, "\t aux: %" PRId64 "\n", ptr->aux ); + fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte ); + if( ptr->phld) + print_placeholder( ptr->phld); + else + fprintf( logstream, "\t res_offset: %#" PRIx64 "\n", ptr->res_offset ); + fprintf( logstream, "\n"); + + ptr = ptr->next; + } +} + +void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue); + +void enqueue_mainheader( msgqueue_param_t *msgqueue) +{ + cachemodel_param_t *cachemodel; + target_param_t *target; + index_param_t *codeidx; + message_param_t *msg; + + cachemodel = msgqueue->cachemodel; + target = cachemodel->target; + codeidx = target->codeidx; + + msg = (message_param_t *)malloc( sizeof(message_param_t)); + + msg->last_byte = true; + msg->in_class_id = 0; + msg->class_id = MAINHEADER_MSG; + assert( target->csn >= 0 ); + msg->csn = (Byte8_t)target->csn; + msg->bin_offset = 0; + msg->length = codeidx->mhead_length; + msg->aux = 0; /* non exist*/ + msg->res_offset = codeidx->offset; + msg->phld = NULL; + msg->next = NULL; + + enqueue_message( msg, msgqueue); + + cachemodel->mhead_model = true; +} + +void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue) +{ + cachemodel_param_t *cachemodel; + target_param_t *target; + index_param_t *codeidx; + message_param_t *msg; + + cachemodel = msgqueue->cachemodel; + target = cachemodel->target; + codeidx = target->codeidx; + + if( !cachemodel->th_model[ tile_id]){ + msg = (message_param_t *)malloc( sizeof(message_param_t)); + msg->last_byte = true; + assert( tile_id >= 0 ); + msg->in_class_id = (Byte8_t)tile_id; + msg->class_id = TILE_HEADER_MSG; + assert( target->csn >= 0 ); + msg->csn = (Byte8_t)target->csn; + msg->bin_offset = 0; + msg->length = codeidx->tileheader[tile_id]->tlen-2; /* SOT marker segment is removed*/ + msg->aux = 0; /* non exist*/ + msg->res_offset = codeidx->offset + (OPJ_OFF_T)get_elemOff(codeidx->tilepart, 0, (Byte8_t)tile_id) + 2; /* skip SOT marker seg*/ + msg->phld = NULL; + msg->next = NULL; + + enqueue_message( msg, msgqueue); + cachemodel->th_model[ tile_id] = true; + } +} + +void enqueue_tile( Byte4_t tile_id, int level, msgqueue_param_t *msgqueue) +{ + cachemodel_param_t *cachemodel; + target_param_t *target; + bool *tp_model; + Byte8_t numOftparts; /* num of tile parts par tile*/ + Byte8_t numOftiles; + index_param_t *codeidx; + faixbox_param_t *tilepart; + message_param_t *msg; + Byte8_t binOffset, binLength, class_id; + Byte8_t i; + + cachemodel = msgqueue->cachemodel; + target = cachemodel->target; + codeidx = target->codeidx; + tilepart = codeidx->tilepart; + + numOftparts = get_nmax( tilepart); + numOftiles = get_m( tilepart); + + class_id = (numOftparts==1) ? TILE_MSG : EXT_TILE_MSG; + + if( /*tile_id < 0 ||*/ numOftiles <= (Byte8_t)tile_id){ + fprintf( FCGI_stderr, "Error, Invalid tile-id %d\n", tile_id); + return; + } + + tp_model = &cachemodel->tp_model[ tile_id*numOftparts]; + + binOffset=0; + for( i=0; i<numOftparts-(Byte8_t)level; i++){ + binLength = get_elemLen( tilepart, i, tile_id); + + if( !tp_model[i]){ + msg = (message_param_t *)malloc( sizeof(message_param_t)); + + msg->last_byte = (i==numOftparts-1); + msg->in_class_id = tile_id; + msg->class_id = class_id; + assert( target->csn >= 0 ); + msg->csn = (Byte8_t)target->csn; + msg->bin_offset = binOffset; + msg->length = binLength; + msg->aux = numOftparts-i; + msg->res_offset = codeidx->offset+(OPJ_OFF_T)get_elemOff( tilepart, i, tile_id)/*-1*/; + msg->phld = NULL; + msg->next = NULL; + + enqueue_message( msg, msgqueue); + + tp_model[i] = true; + } + binOffset += binLength; + } +} + +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, 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); + assert( nmax < INT_MAX ); + if( layers < 0) + layers = numOflayers; + assert( tile_id >= 0 ); + + binOffset = 0; + for( layer_id = 0; layer_id < layers; layer_id++){ + + binLength = get_elemLen( precpacket, (Byte8_t)(seq_id*numOflayers+layer_id), (Byte8_t)tile_id); + + if( !cachemodel->pp_model[comp_id][tile_id*(int)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, (int)codeidx->SIZ.XTnum * (int) codeidx->SIZ.YTnum); + msg->class_id = PRECINCT_MSG; + msg->csn = (Byte8_t)cachemodel->target->csn; + msg->bin_offset = binOffset; + msg->length = binLength; + msg->aux = 0; + msg->res_offset = codeidx->offset+(OPJ_OFF_T)get_elemOff( precpacket, (Byte8_t)(seq_id*numOflayers+layer_id), (Byte8_t)tile_id); + msg->phld = NULL; + msg->next = NULL; + + enqueue_message( msg, msgqueue); + + cachemodel->pp_model[comp_id][tile_id*(int)nmax+seq_id*numOflayers+layer_id] = true; + } + binOffset += binLength; + } +} + +/* MM FIXME: each params is coded on int, this is really not clear from the specs what it should be */ +Byte8_t comp_precinct_id( int t, int c, int s, int num_components, int num_tiles) +{ + return (Byte8_t)(t + (c + s * num_components ) * num_tiles); +} + +void enqueue_box( Byte8_t meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset); +void enqueue_phld( Byte8_t meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset); +void enqueue_boxcontents( Byte8_t meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset); + +void enqueue_metadata( Byte8_t meta_id, msgqueue_param_t *msgqueue) +{ + metadatalist_param_t *metadatalist; + metadata_param_t *metadata; + Byte8_t binOffset; + + metadatalist = msgqueue->cachemodel->target->codeidx->metadatalist; + metadata = search_metadata( meta_id, metadatalist); + + if( !metadata){ + fprintf( FCGI_stderr, "Error: metadata-bin %" PRIu64 " not found\n", meta_id); + return; + } + binOffset = 0; + + if( metadata->boxlist) + enqueue_box( meta_id, metadata->boxlist, msgqueue, &binOffset); + + if( metadata->placeholderlist) + enqueue_phld( meta_id, metadata->placeholderlist, msgqueue, &binOffset); + + if( metadata->boxcontents) + enqueue_boxcontents( meta_id, metadata->boxcontents, msgqueue, &binOffset); + + msgqueue->last->last_byte = true; +} + +message_param_t * gene_metamsg( Byte8_t meta_id, Byte8_t binoffset, Byte8_t length, OPJ_OFF_T res_offset, placeholder_param_t *phld, Byte8_t csn); + +void enqueue_box( Byte8_t meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset) +{ + box_param_t *box; + message_param_t *msg; + + box = boxlist->first; + assert( msgqueue->cachemodel->target->csn >= 0); + while( box){ + msg = gene_metamsg( meta_id, *binOffset, box->length, box->offset, NULL, (Byte8_t)msgqueue->cachemodel->target->csn); + enqueue_message( msg, msgqueue); + + *binOffset += box->length; + box = box->next; + } +} + +void enqueue_phld( Byte8_t meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset) +{ + placeholder_param_t *phld; + message_param_t *msg; + + phld = phldlist->first; + assert( msgqueue->cachemodel->target->csn >= 0); + while( phld){ + msg = gene_metamsg( meta_id, *binOffset, phld->LBox, 0, phld, (Byte8_t)msgqueue->cachemodel->target->csn); + enqueue_message( msg, msgqueue); + + *binOffset += phld->LBox; + phld = phld->next; + } +} + +void enqueue_boxcontents( Byte8_t meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset) +{ + message_param_t *msg; + + assert(msgqueue->cachemodel->target->csn >= 0); + msg = gene_metamsg( meta_id, *binOffset, boxcontents->length, + boxcontents->offset, NULL, (Byte8_t)msgqueue->cachemodel->target->csn); + enqueue_message( msg, msgqueue); + + *binOffset += boxcontents->length; +} + +message_param_t * gene_metamsg( Byte8_t meta_id, Byte8_t binOffset, Byte8_t length, OPJ_OFF_T res_offset, placeholder_param_t *phld, Byte8_t csn) +{ + message_param_t *msg; + + msg = (message_param_t *)malloc( sizeof(message_param_t)); + + msg->last_byte = false; + msg->in_class_id = meta_id; + msg->class_id = METADATA_MSG; + msg->csn = csn; + msg->bin_offset = binOffset; + msg->length = length; + msg->aux = 0; /* non exist*/ + msg->res_offset = res_offset; + msg->phld = phld; + msg->next = NULL; + + return msg; +} + +void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue) +{ + if( msgqueue->first) + msgqueue->last->next = msg; + else + msgqueue->first = msg; + + msgqueue->last = msg; +} + +void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd); +void add_vbas_stream( Byte8_t code, int tmpfd); +void add_body_stream( message_param_t *msg, int fd, int tmpfd); +void add_placeholder_stream( placeholder_param_t *phld, int tmpfd); + +void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd) +{ + message_param_t *msg; + Byte8_t class_id, csn; + Byte_t bb, c; + + if( !(msgqueue)) + return; + + msg = msgqueue->first; + class_id = (Byte8_t)-1; + csn = (Byte8_t)-1; + while( msg){ + if( msg->csn == csn){ + if( msg->class_id == class_id) + bb = 1; + else{ + bb = 2; + class_id = msg->class_id; + } + } + else{ + bb = 3; + class_id = msg->class_id; + csn = msg->csn; + } + + c = msg->last_byte ? 1 : 0; + + add_bin_id_vbas_stream( bb, c, msg->in_class_id, tmpfd); + + if( bb >= 2) + add_vbas_stream( class_id, tmpfd); + if (bb == 3) + add_vbas_stream( csn, tmpfd); + + add_vbas_stream( msg->bin_offset, tmpfd); + add_vbas_stream (msg->length, tmpfd); + + if( msg->class_id%2) /* Aux is present only if the id is odd*/ + add_vbas_stream( msg->aux, tmpfd); + + if( msg->phld) + add_placeholder_stream( msg->phld, tmpfd); + else + add_body_stream( msg, msgqueue->cachemodel->target->fd, tmpfd); + + msg = msg->next; + } +} + +void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd); +void print_binarycode( Byte8_t n, int segmentlen); + +void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd) +{ + int bytelength; + Byte8_t tmp; + + /* A.2.3 In-class identifiers */ + /* 7k-3bits, where k is the number of bytes in the VBAS*/ + bytelength = 1; + tmp = in_class_id >> 4; + while( tmp){ + bytelength ++; + tmp >>= 7; + } + + in_class_id |= (Byte8_t)((((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7)); + + add_vbas_with_bytelen_stream( in_class_id, bytelength, tmpfd); +} + +void add_vbas_stream( Byte8_t code, int tmpfd) +{ + int bytelength; + Byte8_t tmp; + + bytelength = 1; + tmp = code; + while( tmp >>= 7) + bytelength ++; + + add_vbas_with_bytelen_stream( code, bytelength, tmpfd); +} + +void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd) +{ + int n; + Byte8_t seg; + + n = bytelength - 1; + while( n >= 0) { + seg = ( code >> (n*7)) & 0x7f; + if( n) + seg |= 0x80; + if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){ + fprintf( FCGI_stderr, "Error: failed to write vbas\n"); + return; + } + n--; + } +} + +void add_body_stream( message_param_t *msg, int fd, int tmpfd) +{ + Byte_t *data; + + if( !(data = fetch_bytes( fd, msg->res_offset, msg->length))){ + fprintf( FCGI_stderr, "Error: fetch_bytes in add_body_stream()\n"); + return; + } + + if( write( tmpfd, data, msg->length) < 1){ + free( data); + fprintf( FCGI_stderr, "Error: fwrite in add_body_stream()\n"); + return; + } + free(data); +} + +void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd); + +void add_placeholder_stream( placeholder_param_t *phld, int tmpfd) +{ + add_bigendian_bytestream( phld->LBox, 4, tmpfd); + if( write( tmpfd, phld->TBox, 4) < 1){ + fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n"); + return; + } + add_bigendian_bytestream( phld->Flags, 4, tmpfd); + add_bigendian_bytestream( phld->OrigID, 8, tmpfd); + + if( write( tmpfd, phld->OrigBH, phld->OrigBHlen) < 1){ + fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n"); + return; + } +} + +void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd) +{ + int n; + Byte8_t seg; + + n = bytelength - 1; + while( n >= 0) { + seg = ( code >> (n*8)) & 0xff; + if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){ + fprintf( FCGI_stderr, "ERROR: failed to write bigendian_bytestream\n"); + return; + } + n--; + } +} + +void print_binarycode( Byte8_t n, int segmentlen) +{ + char buf[256]; + int i=0, j, k; + + do{ + buf[i++] = n%2 ? '1' : '0'; + }while((n=n/2)); + + for( j=segmentlen-1; j>=i; j--) + putchar('0'); + + for( j=i-1, k=0; j>=0; j--, k++){ + putchar( buf[j]); + if( !((k+1)%segmentlen)) + printf(" "); + } + printf("\n"); +} + +Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id); +Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem); + +void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, OPJ_OFF_T offset, msgqueue_param_t *msgqueue) +{ + Byte_t *ptr; /* stream pointer*/ + message_param_t *msg; + Byte_t bb, c; + Byte8_t class_id, csn; + + class_id = (Byte8_t)-1; /* dummy*/ + csn = (Byte8_t)-1; + ptr = JPIPstream; + while( (Byte8_t)(ptr-JPIPstream) < streamlen){ + msg = (message_param_t *)malloc( sizeof(message_param_t)); + + ptr = parse_bin_id_vbas( ptr, &bb, &c, &msg->in_class_id); + + msg->last_byte = c == 1 ? true : false; + + if( bb >= 2) + ptr = parse_vbas( ptr, &class_id); + + msg->class_id = class_id; + + if (bb == 3) + ptr = parse_vbas( ptr, &csn); + msg->csn = csn; + + ptr = parse_vbas( ptr, &msg->bin_offset); + ptr = parse_vbas( ptr, &msg->length); + + if( msg->class_id%2) /* Aux is present only if the id is odd*/ + ptr = parse_vbas( ptr, &msg->aux); + else + msg->aux = 0; + + msg->res_offset = ptr-JPIPstream+offset; + msg->phld = NULL; + msg->next = NULL; + + if(msgqueue->first) + msgqueue->last->next = msg; + else + msgqueue->first = msg; + msgqueue->last = msg; + + ptr += msg->length; + } +} + +void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *stream); + +void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist) +{ + message_param_t *msg; + (void)streamlen; + + if( metadatalist == NULL) + return; + + msg = msgqueue->first; + while( msg){ + if( msg->class_id == METADATA_MSG){ + metadata_param_t *metadata = gene_metadata( msg->in_class_id, NULL, NULL, NULL); + insert_metadata_into_list( metadata, metadatalist); + parse_metadata( metadata, msg, stream+msg->res_offset); + } + msg = msg->next; + } +} + +placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength); + +void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *datastream) +{ + box_param_t *box; + placeholder_param_t *phld; + char *boxtype = (char *)(datastream+4); + + msg->phld = NULL; + + if( strncmp( boxtype, "phld", 4) == 0){ + if( !metadata->placeholderlist) + metadata->placeholderlist = gene_placeholderlist(); + + phld = parse_phld( datastream, msg->length); + msg->phld = phld; + insert_placeholder_into_list( phld, metadata->placeholderlist); + } + else if( isalpha(boxtype[0]) && isalpha(boxtype[1]) && + (isalnum(boxtype[2])||isspace(boxtype[2])) && + (isalpha(boxtype[3])||isspace(boxtype[3]))){ + if( !metadata->boxlist) + metadata->boxlist = gene_boxlist(); + + box = gene_boxbyOffinStream( datastream, msg->res_offset); + insert_box_into_list( box, metadata->boxlist); + } + else + metadata->boxcontents = gene_boxcontents( msg->res_offset, msg->length); +} + +placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength) +{ + placeholder_param_t *phld; + + phld = (placeholder_param_t *)malloc( sizeof(placeholder_param_t)); + + phld->LBox = big4( datastream); + strcpy( phld->TBox, "phld"); + phld->Flags = big4( datastream+8); + phld->OrigID = big8( datastream+12); + phld->OrigBHlen = (Byte_t)(metalength - 20); + phld->OrigBH = (Byte_t *)malloc(phld->OrigBHlen); + memcpy( phld->OrigBH, datastream+20, phld->OrigBHlen); + phld->next = NULL; + + return phld; +} + +Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id) +{ + Byte_t code; + Byte_t *ptr; + + ptr = streamptr; + code = *(ptr++); + + *bb = (code >> 5) & 3; + *c = (code >> 4) & 1; + + *in_class_id = code & 15; + + while(code >> 7){ + code = *(ptr++); + *in_class_id = (*in_class_id << 7) | (code & 0x7f); + } + return ptr; +} + +Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem) +{ + Byte_t code; + Byte_t *ptr; + + *elem = 0; + ptr = streamptr; + do{ + code = *(ptr++); + *elem = (*elem << 7) | (code & 0x7f); + }while(code >> 7); + + return ptr; +} + +void delete_message_in_msgqueue( message_param_t **msg, msgqueue_param_t *msgqueue) +{ + message_param_t *ptr; + + if( !(*msg)) + return; + + if( *msg == msgqueue->first) + msgqueue->first = (*msg)->next; + else{ + ptr = msgqueue->first; + while( ptr->next != *msg){ + ptr=ptr->next; + } + + ptr->next = (*msg)->next; + + if( *msg == msgqueue->last) + msgqueue->last = ptr; + } + free( *msg); +} diff --git a/src/lib/openjpip/msgqueue_manager.h b/src/lib/openjpip/msgqueue_manager.h new file mode 100644 index 00000000..e54f2dc1 --- /dev/null +++ b/src/lib/openjpip/msgqueue_manager.h @@ -0,0 +1,188 @@ +/* + * $Id: msgqueue_manager.h 53 2011-05-09 16:55:39Z kaori $ + * + * 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 MSGQUEUE_MANAGER_H_ +# define MSGQUEUE_MANAGER_H_ + +#include "bool.h" +#include "byte_manager.h" +#include "cachemodel_manager.h" +#include "placeholder_manager.h" + +#define PRECINCT_MSG 0 +#define EXT_PRECINCT_MSG 1 +#define TILE_HEADER_MSG 2 +#define TILE_MSG 4 +#define EXT_TILE_MSG 5 +#define MAINHEADER_MSG 6 +#define METADATA_MSG 8 + +/** message parameters */ +typedef struct message_param{ + bool last_byte; /**< if message contains the last byte of the data-bin*/ + Byte8_t in_class_id; /**< in-class identifier A.2.3*/ + Byte8_t class_id; /**< class identifiers */ + Byte8_t csn; /**< index of the codestream*/ + Byte8_t bin_offset; /**< offset of the data in this message from the start of the data-bin*/ + Byte8_t length; /**< message byte length*/ + Byte8_t aux; /**<*/ + OPJ_OFF_T res_offset; /**< offset in the resource*/ + placeholder_param_t *phld; /**< placeholder pointer in index*/ + struct message_param *next; /**< pointer to the next message*/ +} message_param_t; + +/** message queue parameters */ +typedef struct msgqueue_param{ + message_param_t *first; /**< first message pointer of the list*/ + message_param_t *last; /**< last message pointer of the list*/ + bool stateless; /**< if this is a stateless message queue*/ + cachemodel_param_t *cachemodel; /**< reference cachemodel pointer*/ +} msgqueue_param_t; + +/** + * generate message queue + * + * @param[in] stateless if this is a stateless message queue + * @param[in] cachemodel cachemodel pointer + * @return generated message queue pointer + */ +msgqueue_param_t * gene_msgqueue( bool stateless, cachemodel_param_t *cachemodel); + +/** + * delete message queue + * + * @param[in] msgqueue address of the message queue pointer + */ +void delete_msgqueue( msgqueue_param_t **msgqueue); + +/** + * delete a message in msgqueue + * + * @param[in] message address of the deleting message pointer + * @param[in] msgqueue message queue pointer + */ +void delete_message_in_msgqueue( message_param_t **message, msgqueue_param_t *msgqueue); + +/** + * print message queue + * + * @param[in] msgqueue message queue pointer + */ +void print_msgqueue( msgqueue_param_t *msgqueue); + + +/** + * enqueue main header data-bin into message queue + * + * @param[in,out] msgqueue message queue pointer + */ +void enqueue_mainheader( msgqueue_param_t *msgqueue); + +/** + * enqueue tile headers data-bin into message queue + * + * @param[in] tile_id tile id starting from 0 + * @param[in,out] msgqueue message queue pointer + */ +void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue); + +/** + * enqueue tile data-bin into message queue + * + * @param[in] tile_id tile id starting from 0 + * @param[in] level decomposition level + * @param[in,out] msgqueue message queue pointer + */ +void enqueue_tile( Byte4_t tile_id, int level, msgqueue_param_t *msgqueue); + +/** + * enqueue precinct data-bin into message queue + * + * @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, int layers, msgqueue_param_t *msgqueue); + + +/** + * enqueue Metadata-bin into message queue + * + * @param[in] meta_id metadata-bin id + * @param[in,out] msgqueue message queue pointer + */ +void enqueue_metadata( Byte8_t meta_id, msgqueue_param_t *msgqueue); + + +/** + * reconstruct JPT/JPP-stream from message queue + * + * @param[in] msgqueue message queue pointer + * @param[in] tmpfd file discriptor to write JPT/JPP-stream + */ +void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd); + + +/** + * parse JPT- JPP- stream to message queue + * + * @param[in] JPIPstream JPT- JPP- stream data pointer + * @param[in] streamlen JPIPstream length + * @param[in] offset offset of the stream from the whole beginning + * @param[in,out] msgqueue adding message queue pointer + */ +void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, OPJ_OFF_T offset, msgqueue_param_t *msgqueue); + +/** + * parse JPT- JPP- stream to message queue + * + * @param[in] msgqueue reference message queue pointer + * @param[in] stream stream data pointer + * @param[in] streamlen stream length + * @param[in] metadatalist adding metadata list pointer + */ +void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist); + +/** + * compute precinct ID A.3.2.1 + * + * @param[in] t tile index + * @param[in] c component index + * @param[in] s sequence number + * @param[in] num_components total number of components + * @param[in] num_tiles total number of tiles + * @return precicnt id + */ +Byte8_t comp_precinct_id( int t, int c, int s, int num_components, int num_tiles); + +#endif /* !MSGQUEUE_MANAGER_H_ */ diff --git a/src/lib/openjpip/openjpip.c b/src/lib/openjpip/openjpip.c new file mode 100644 index 00000000..de6293d4 --- /dev/null +++ b/src/lib/openjpip/openjpip.c @@ -0,0 +1,450 @@ +/* + * $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 <stdlib.h> +#include "openjpip.h" +#include "jpip_parser.h" +#include "channel_manager.h" +#include "byte_manager.h" +#ifdef _WIN32 +#include <io.h> +#else +#include <unistd.h> +#endif + +#ifdef SERVER +#include "auxtrans_manager.h" +#endif + +#include <stdio.h> +#include "dec_clientmsg_handler.h" +#include "jpipstream_manager.h" + +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "jp2k_encoder.h" + +#ifdef SERVER + +server_record_t * init_JPIPserver( int tcp_auxport, int udp_auxport) +{ + server_record_t *record = (server_record_t *)malloc( sizeof(server_record_t)); + + record->sessionlist = gene_sessionlist(); + record->targetlist = gene_targetlist(); + record->auxtrans = init_aux_transport( tcp_auxport, udp_auxport); + + return record; +} + +void terminate_JPIPserver( server_record_t **rec) +{ + delete_sessionlist( &(*rec)->sessionlist); + delete_targetlist( &(*rec)->targetlist); + close_aux_transport( (*rec)->auxtrans); + + free( *rec); +} + +QR_t * parse_querystring( const char *query_string) +{ + QR_t *qr; + + qr = (QR_t *)malloc( sizeof(QR_t)); + + qr->query = parse_query( query_string); + qr->msgqueue = NULL; + qr->channel = NULL; + + return qr; +} + +bool process_JPIPrequest( server_record_t *rec, QR_t *qr) +{ + target_param_t *target = NULL; + session_param_t *cursession = NULL; + channel_param_t *curchannel = NULL; + + if( qr->query->target || qr->query->tid){ + if( !identify_target( *(qr->query), rec->targetlist, &target)) + return false; + } + + if( qr->query->cid){ + if( !associate_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel)) + return false; + qr->channel = curchannel; + } + + if( qr->query->cnew != non){ + if( !open_channel( *(qr->query), rec->sessionlist, rec->auxtrans, target, &cursession, &curchannel)) + return false; + qr->channel = curchannel; + } + + if( qr->query->cclose) + if( !close_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel)) + return false; + + if( (qr->query->fx > 0 && qr->query->fy > 0) || qr->query->box_type[0][0] != 0 || qr->query->len > 0) + if( !gene_JPIPstream( *(qr->query), target, cursession, curchannel, &qr->msgqueue)) + return false; + + return true; +} + +void add_EORmsg( int fd, QR_t *qr); + +void send_responsedata( server_record_t *rec, QR_t *qr) +{ + int fd; + const char tmpfname[] = "tmpjpipstream.jpp"; + Byte_t *jpipstream; + Byte8_t len_of_jpipstream; + + if( (fd = open( tmpfname, O_RDWR|O_CREAT|O_EXCL, S_IRWXU)) == -1){ + fprintf( FCGI_stderr, "file open error %s", tmpfname); + fprintf( FCGI_stdout, "Status: 503\r\n"); + fprintf( FCGI_stdout, "Reason: Implementation failed\r\n"); + return; + } + + recons_stream_from_msgqueue( qr->msgqueue, fd); + + add_EORmsg( fd, qr); /* needed at least for tcp and udp */ + + len_of_jpipstream = (Byte8_t)get_filesize( fd); + jpipstream = fetch_bytes( fd, 0, len_of_jpipstream); + + close( fd); + remove( tmpfname); + + fprintf( FCGI_stdout, "\r\n"); + + if( len_of_jpipstream){ + + if( qr->channel) + if( qr->channel->aux == tcp || qr->channel->aux == udp){ + send_responsedata_on_aux( qr->channel->aux==tcp, rec->auxtrans, qr->channel->cid, jpipstream, len_of_jpipstream, 1000); /* 1KB per frame*/ + return; + } + + if( fwrite( jpipstream, len_of_jpipstream, 1, FCGI_stdout) != 1) + fprintf( FCGI_stderr, "Error: failed to write jpipstream\n"); + } + + free( jpipstream); + + return; +} + +void add_EORmsg( int fd, QR_t *qr) +{ + unsigned char EOR[3]; + + if( qr->channel){ + EOR[0] = 0x00; + EOR[1] = is_allsent( *(qr->channel->cachemodel)) ? 0x01 : 0x02; + EOR[2] = 0x00; + if( write( fd, EOR, 3) != 3) + fprintf( FCGI_stderr, "Error: failed to write EOR message\n"); + } +} + +void end_QRprocess( server_record_t *rec, QR_t **qr) +{ + /* TODO: record client preferences if necessary*/ + (void)rec; /* unused */ + delete_query( &((*qr)->query)); + delete_msgqueue( &((*qr)->msgqueue)); + free( *qr); +} + + +void local_log( bool query, bool messages, bool sessions, bool targets, QR_t *qr, server_record_t *rec) +{ + if( query) + print_queryparam( *qr->query); + + if( messages) + print_msgqueue( qr->msgqueue); + + if( sessions) + print_allsession( rec->sessionlist); + + if( targets) + print_alltarget( rec->targetlist); +} + +#endif /*SERVER*/ + +#ifndef SERVER + +dec_server_record_t * init_dec_server( int port) +{ + dec_server_record_t *record = (dec_server_record_t *)malloc( sizeof(dec_server_record_t)); + + record->cachelist = gene_cachelist(); + record->jpipstream = NULL; + record->jpipstreamlen = 0; + record->msgqueue = gene_msgqueue( true, NULL); + record->listening_socket = open_listeningsocket( (uint16_t)port); + + return record; +} + +void terminate_dec_server( dec_server_record_t **rec) +{ + delete_cachelist( &(*rec)->cachelist); + free( (*rec)->jpipstream); + + if( (*rec)->msgqueue) + delete_msgqueue( &((*rec)->msgqueue)); + + if( close_socket( (*rec)->listening_socket) != 0) + perror("close"); + + free( *rec); +} + +client_t accept_connection( dec_server_record_t *rec) +{ + client_t client; + + client = accept_socket( rec->listening_socket); + if( client == -1) + fprintf( stderr, "error: failed to connect to client\n"); + + return client; +} + +bool handle_clientreq( client_t client, dec_server_record_t *rec) +{ + bool quit = false; + msgtype_t msgtype = identify_clientmsg( client); + + switch( msgtype){ + case JPIPSTREAM: + handle_JPIPstreamMSG( client, rec->cachelist, &rec->jpipstream, &rec->jpipstreamlen, rec->msgqueue); + break; + + case PNMREQ: + handle_PNMreqMSG( client, rec->jpipstream, rec->msgqueue, rec->cachelist); + break; + + case XMLREQ: + handle_XMLreqMSG( client, rec->jpipstream, rec->cachelist); + break; + + case TIDREQ: + handle_TIDreqMSG( client, rec->cachelist); + break; + + case CIDREQ: + handle_CIDreqMSG( client, rec->cachelist); + break; + + case CIDDST: + handle_dstCIDreqMSG( client, rec->cachelist); + break; + + case SIZREQ: + handle_SIZreqMSG( client, rec->jpipstream, rec->msgqueue, rec->cachelist); + break; + + case JP2SAVE: + handle_JP2saveMSG( client, rec->cachelist, rec->msgqueue, rec->jpipstream); + break; + + case QUIT: + quit = true; + save_codestream( rec->jpipstream, rec->jpipstreamlen, "jpt"); + break; + case MSGERROR: + break; + } + + fprintf( stderr, "\t end of the connection\n\n"); + if( close_socket(client) != 0){ + perror("close"); + return false; + } + + if( quit) + return false; + + return true; +} + + +jpip_dec_param_t * init_jpipdecoder( bool jp2) +{ + jpip_dec_param_t *dec; + + dec = (jpip_dec_param_t *)calloc( 1, sizeof(jpip_dec_param_t)); + + dec->msgqueue = gene_msgqueue( true, NULL); + + if( jp2) + dec->metadatalist = gene_metadatalist(); + + return dec; +} + + +bool fread_jpip( const char fname[], jpip_dec_param_t *dec) +{ + int infd; + + if(( infd = open( fname, O_RDONLY)) == -1){ + fprintf( stderr, "file %s not exist\n", fname); + return false; + } + + if(!(dec->jpiplen = (Byte8_t)get_filesize(infd))) + return false; + + dec->jpipstream = (Byte_t *)malloc( dec->jpiplen); + + if( read( infd, dec->jpipstream, dec->jpiplen) != (int)dec->jpiplen){ + fprintf( stderr, "file reading error\n"); + free( dec->jpipstream); + return false; + } + + close(infd); + + return true; +} + +void decode_jpip( jpip_dec_param_t *dec) +{ + parse_JPIPstream( dec->jpipstream, dec->jpiplen, 0, dec->msgqueue); + + if( dec->metadatalist){ /* JP2 encoding*/ + parse_metamsg( dec->msgqueue, dec->jpipstream, dec->jpiplen, dec->metadatalist); + dec->ihdrbox = gene_ihdrbox( dec->metadatalist, dec->jpipstream); + + dec->jp2kstream = recons_jp2( dec->msgqueue, dec->jpipstream, dec->msgqueue->first->csn, &dec->jp2klen); + } + else /* J2k encoding */ + /* Notice: arguments fw, fh need to be set for LRCP, PCRL, CPRL*/ + dec->jp2kstream = recons_j2k( dec->msgqueue, dec->jpipstream, dec->msgqueue->first->csn, 0, 0, &dec->jp2klen); +} + +bool fwrite_jp2k( const char fname[], jpip_dec_param_t *dec) +{ + int outfd; + +#ifdef _WIN32 + if(( outfd = open( fname, O_WRONLY|O_CREAT, _S_IREAD | _S_IWRITE)) == -1){ +#else + if(( outfd = open( fname, O_WRONLY|O_CREAT, S_IRWXU|S_IRWXG)) == -1){ +#endif + fprintf( stderr, "file %s open error\n", fname); + return false; + } + + if( write( outfd, dec->jp2kstream, dec->jp2klen) != (int)dec->jp2klen) + fprintf( stderr, "j2k file write error\n"); + + close(outfd); + + return true; +} + +void output_log( bool messages, bool metadata, bool ihdrbox, jpip_dec_param_t *dec) +{ + if( messages) + print_msgqueue( dec->msgqueue); + + if( metadata) + print_allmetadata( dec->metadatalist); + + if( ihdrbox){ + printf("W*H: %d*%d\n", dec->ihdrbox->height, dec->ihdrbox->width); + printf("NC: %d, bpc: %d\n", dec->ihdrbox->nc, dec->ihdrbox->bpc); + } +} + +void destroy_jpipdecoder( jpip_dec_param_t **dec) +{ + free( (*dec)->jpipstream); + delete_msgqueue( &(*dec)->msgqueue); + if( (*dec)->metadatalist){ + delete_metadatalist( &(*dec)->metadatalist); + free( (*dec)->ihdrbox); + } + + free( (*dec)->jp2kstream); + free( *dec); +} + +index_t * get_index_from_JP2file( int fd) +{ + char *data; + + /* Check resource is a JP family file.*/ + if( lseek( fd, 0, SEEK_SET)==-1){ + fprintf( stderr, "Error: File broken (lseek error)\n"); + return NULL; + } + + data = (char *)malloc( 12); /* size of header*/ + if( read( fd, data, 12) != 12){ + free( data); + fprintf( stderr, "Error: File broken (read error)\n"); + return NULL; + } + + if( *data || *(data + 1) || *(data + 2) || + *(data + 3) != 12 || strncmp (data + 4, "jP \r\n\x87\n", 8)){ + free( data); + fprintf( stderr, "Error: No JPEG 2000 Signature box in this file\n"); + return NULL; + } + free( data); + + return parse_jp2file( fd); +} + +void destroy_index( index_t **idx) +{ + delete_index( idx); +} + +void output_index( index_t *index) +{ + print_index( *index); +} + +#endif /*SERVER*/ diff --git a/src/lib/openjpip/openjpip.h b/src/lib/openjpip/openjpip.h new file mode 100644 index 00000000..c08c3d86 --- /dev/null +++ b/src/lib/openjpip/openjpip.h @@ -0,0 +1,308 @@ +/* + * $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. + */ + +#ifndef OPENJPIP_H_ +# define OPENJPIP_H_ + +#include "session_manager.h" +#include "target_manager.h" +#include "query_parser.h" +#include "msgqueue_manager.h" +#include "bool.h" +#include "sock_manager.h" +#include "auxtrans_manager.h" + +#ifdef SERVER + +#include "fcgi_stdio.h" +#define logstream FCGI_stdout + +#else + +#define FCGI_stdout stdout +#define FCGI_stderr stderr +#define logstream stderr + +#include "cache_manager.h" +#include "byte_manager.h" +#include "imgsock_manager.h" + +#include "metadata_manager.h" +#include "ihdrbox_manager.h" +#include "index_manager.h" + +#endif /*SERVER*/ + +/* + *========================================================== + * JPIP server API + *========================================================== + */ + + #ifdef SERVER + +/** Server static records*/ +typedef struct server_record{ + sessionlist_param_t *sessionlist; /**< list of session records*/ + targetlist_param_t *targetlist; /**< list of target records*/ + auxtrans_param_t auxtrans; +} server_record_t; + +/** Query/response data for each client*/ +typedef struct QR{ + query_param_t *query; /**< query parameters*/ + msgqueue_param_t *msgqueue; /**< message queue*/ + channel_param_t *channel; /**< channel, (NULL if stateless)*/ +} QR_t; + +/** + * Initialize the JPIP server + * + * @param[in] tcp_auxport opening tcp auxiliary port ( 0 not to open, valid No. 49152-65535) + * @param[in] udp_auxport opening udp auxiliary port ( 0 not to open, valid No. 49152-65535) + * @return intialized server record pointer + */ +server_record_t * init_JPIPserver( int tcp_auxport, int udp_auxport); + +/** + * Terminate the JPIP server + * + * @param[in] rec address of deleting server static record pointer + */ +void terminate_JPIPserver( server_record_t **rec); + +/** + * 1st process per client request; parse query string + * + * @param[in] query_string request query string + * @return initialized query/response data pointer + */ +QR_t * parse_querystring( const char *query_string); + +/** + * 2nd process; process JPIP request and construct message queue + * + * @param[in] rec server static record pointer + * @param[in] qr query/response data pointer + * @return true if succeed, otherwise false + */ +bool process_JPIPrequest( server_record_t *rec, QR_t *qr); + +/** + * 3rd process; send response data JPT/JPP-stream + * + * @param[in] rec server static record pointer + * @param[in] qr query/response data pointer + */ +void send_responsedata( server_record_t *rec, QR_t *qr); + +/** + * 4th (last) process; + * + * @param[in] rec server static record pinter + * @param[in] qr address of query/response data pointer + */ +void end_QRprocess( server_record_t *rec, QR_t **qr); + +/** + * Option for local tests; print out parameter values to logstream (stderr) + * + * @param[in] query true if query parameters are to be printed out + * @param[in] messages true if queue of messages is to be printed out + * @param[in] sessions true if session list is to be printed out + * @param[in] targets true if target list is to be printed out + * @param[in] qr query/response data pointer + * @param[in] rec server static record pinter + */ +void local_log( bool query, bool messages, bool sessions, bool targets, QR_t *qr, server_record_t *rec); + +#endif /*SERVER*/ + +/* + *========================================================== + * JPIP decoding server API + *========================================================== + */ + +#ifndef SERVER + +/** Decoding server static records*/ +typedef struct dec_server_record{ + cachelist_param_t *cachelist; /**< cache list*/ + Byte_t *jpipstream; /**< JPT/JPP stream*/ + OPJ_SIZE_T jpipstreamlen; /**< length of jpipstream*/ + msgqueue_param_t *msgqueue; /**< parsed message queue of jpipstream*/ + SOCKET listening_socket; /**< listenning socket*/ +} dec_server_record_t; + + +/** Client socket identifier*/ +typedef SOCKET client_t; + +/** + * Initialize the image decoding server + * + * @param[in] port opening tcp port (valid No. 49152-65535) + * @return intialized decoding server record pointer + */ +dec_server_record_t * init_dec_server( int port); + +/** + * Terminate the image decoding server + * + * @param[in] rec address of deleting decoding server static record pointer + */ +void terminate_dec_server( dec_server_record_t **rec); + +/** + * Accept client connection + * + * @param[in] rec decoding server static record pointer + * @return client socket ID, -1 if failed + */ +client_t accept_connection( dec_server_record_t *rec); + + /** + * Handle client request + * + * @param[in] client client socket ID + * @param[in] rec decoding server static record pointer + * @return true if succeed + */ +bool handle_clientreq( client_t client, dec_server_record_t *rec); + +#endif /*SERVER*/ + +/* + *========================================================== + * JPIP tool API + *========================================================== + */ + +#ifndef SERVER + +/* + * jpip to JP2 or J2K + */ + +/** JPIP decoding parameters*/ +typedef struct jpip_dec_param{ + Byte_t *jpipstream; /**< JPT/JPP-stream*/ + Byte8_t jpiplen; /**< length of jpipstream*/ + msgqueue_param_t *msgqueue; /**< message queue*/ + metadatalist_param_t *metadatalist; /**< metadata list going into JP2 file*/ + ihdrbox_param_t *ihdrbox; /**< ihdr box going into JP2 file*/ + Byte_t *jp2kstream; /**< J2K codestream or JP2 file codestream*/ + Byte8_t jp2klen; /**< length of j2kstream or JP2 file*/ +} jpip_dec_param_t; + +/** + * Initialize jpip decoder + * + * @param[in] jp2 true in case of jp2 file encoding, else j2k file encoding + * @return JPIP decoding parameters pointer + */ +jpip_dec_param_t * init_jpipdecoder( bool jp2); + +/** + * Destroy jpip decoding parameters + * + * @param[in] dec address of JPIP decoding parameters pointer + */ +void destroy_jpipdecoder( jpip_dec_param_t **dec); + +/** + * Read jpip codestream from a file + * + * @param[in] fname file name + * @param[in] dec JPIP decoding parameters pointer + * @return true if succeed + */ +bool fread_jpip( const char fname[], jpip_dec_param_t *dec); + +/** + * Decode jpip codestream + * + * @param[in] dec JPIP decoding parameters pointer + */ +void decode_jpip( jpip_dec_param_t *dec); + +/** + * Write J2K/JP2 codestream to a file + * + * @param[in] fname file name + * @param[in] dec JPIP decoding parameters pointer + * @return true if succeed + */ +bool fwrite_jp2k( const char fname[], jpip_dec_param_t *dec); + +/** + * Option; print out parameter values to stderr + * + * @param[in] messages true if queue of messages is to be printed out + * @param[in] metadata true if metadata is to be printed out + * @param[in] ihdrbox true if image header data is to be printed out + * @param[in] dec JPIP decoding parameters pointer + */ +void output_log( bool messages, bool metadata, bool ihdrbox, jpip_dec_param_t *dec); + +/* + * test the format of index (cidx) box in JP2 file + */ + +/** Redefinition of index parameters*/ +typedef index_param_t index_t; + +/** + * Parse JP2 file and get index information from cidx box inside + * + * @param[in] fd file descriptor of the JP2 file + * @return pointer to the generated structure of index parameters + */ +index_t * get_index_from_JP2file( int fd); + +/** + * Destroy index parameters + * + * @param[in,out] idx addressof the index pointer + */ +void destroy_index( index_t **idx); + + +/** + * print index parameters + * + * @param[in] index index parameters + */ +void output_index( index_t *index); + +#endif /*SERVER*/ + +#endif /* !OPENJPIP_H_ */ diff --git a/src/lib/openjpip/placeholder_manager.c b/src/lib/openjpip/placeholder_manager.c new file mode 100644 index 00000000..4a37a13b --- /dev/null +++ b/src/lib/openjpip/placeholder_manager.c @@ -0,0 +1,143 @@ +/* + * $Id: placeholder_manager.c 53 2011-05-09 16:55:39Z kaori $ + * + * 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 "placeholder_manager.h" +#include "opj_inttypes.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*/ + + + +placeholderlist_param_t * gene_placeholderlist(void) +{ + placeholderlist_param_t *list; + + list = (placeholderlist_param_t *)malloc( sizeof(placeholderlist_param_t)); + + list->first = NULL; + list->last = NULL; + + return list; +} + +void delete_placeholderlist( placeholderlist_param_t **list) +{ + placeholder_param_t *ptr, *next; + + if(!(*list)) + return; + + ptr = (*list)->first; + + while( ptr){ + next=ptr->next; + delete_placeholder( &ptr); + ptr=next; + } + free( *list); +} + +placeholder_param_t * gene_placeholder( box_param_t *box, Byte8_t origID) +{ + placeholder_param_t *placeholder; + + placeholder = (placeholder_param_t *)malloc( sizeof(placeholder_param_t)); + + strncpy( placeholder->TBox, "phld", 4); + placeholder->Flags = 1; /* only the access to the original contents of this box, for now */ + placeholder->OrigID = origID; + placeholder->OrigBH = fetch_headbytes( box); + placeholder->OrigBHlen = box->headlen; + placeholder->LBox = 20+(Byte4_t)box->headlen; + placeholder->next = NULL; + + return placeholder; +} + +void delete_placeholder( placeholder_param_t **placeholder) +{ + if( (*placeholder)->OrigBH) + free((*placeholder)->OrigBH); + free(*placeholder); +} + +void insert_placeholder_into_list( placeholder_param_t *phld, placeholderlist_param_t *phldlist) +{ + if( phldlist->first) + phldlist->last->next = phld; + else + phldlist->first = phld; + phldlist->last = phld; +} + +void print_placeholder( placeholder_param_t *phld) +{ + int i; + + fprintf( logstream, "placeholder info:\n"); + fprintf( logstream, "\t LBox: %d %#x\n", phld->LBox, phld->LBox); + fprintf( logstream, "\t TBox: %.4s\n", phld->TBox); + fprintf( logstream, "\t Flags: %#x %#x\n", phld->Flags, phld->Flags); + fprintf( logstream, "\t OrigID: %" PRId64 "\n", phld->OrigID); + fprintf( logstream, "\t OrigBH: "); + + for( i=0; i< phld->OrigBHlen; i++) + fprintf( logstream, "%02x ", phld->OrigBH[i]); + fprintf( logstream, "\t"); + + for( i=0; i< phld->OrigBHlen; i++) + fprintf( logstream, "%c", phld->OrigBH[i]); + fprintf( logstream, "\n"); +} + +void print_allplaceholder( placeholderlist_param_t *list) +{ + placeholder_param_t *ptr; + + if( !list) + return; + + fprintf( logstream, "all placeholder info: \n"); + ptr = list->first; + while( ptr != NULL){ + print_placeholder( ptr); + ptr=ptr->next; + } +} diff --git a/src/lib/openjpip/placeholder_manager.h b/src/lib/openjpip/placeholder_manager.h new file mode 100644 index 00000000..ced20854 --- /dev/null +++ b/src/lib/openjpip/placeholder_manager.h @@ -0,0 +1,115 @@ +/* + * $Id: placeholder_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef PLACEHOLDER_MANAGER_H_ +# define PLACEHOLDER_MANAGER_H_ + +#include "byte_manager.h" +#include "box_manager.h" + +/** A.3.6.3 Placeholder box format*/ +/** placeholder box parameters*/ +typedef struct placeholder_param{ + Byte4_t LBox; + char TBox[4]; + Byte4_t Flags; + Byte8_t OrigID; + Byte_t *OrigBH; /**< dynamic memory pointer*/ + Byte_t OrigBHlen; /**< length of OrigBH*/ +#ifdef AAA + Byte8_t EquivID; + Byte_t *EquivBH; /**< dynamic memory pointer*/ + Byte_t EquivBHlen; /**< length of EquivBH*/ + Byte8_t CSID; + Byte4_t NCS; +#endif /*AAA*/ + struct placeholder_param *next; /**< pointer to the next placeholder*/ +} placeholder_param_t; + + +/** placeholder box list parameters*/ +typedef struct placeholderlist_param{ + placeholder_param_t *first; /**< first placeholder pointer of the list*/ + placeholder_param_t *last; /**< last placeholder pointer of the list*/ +} placeholderlist_param_t; + + +/** + * generate a placeholder list + * + * @return pointer to the generated placeholder list + */ +placeholderlist_param_t * gene_placeholderlist(void); + + +/** + * delete placeholder list + * + * @param[in,out] list address of the placeholder list pointer + */ +void delete_placeholderlist( placeholderlist_param_t **list); + + +/** + * generate a placeholder of a box + * + * @param[in] box box pointer + * @param[in] origID metadata-bin ID of the bin containing the contents of the original box + * @return pointer to the generated placeholder + */ +placeholder_param_t * gene_placeholder( box_param_t *box, Byte8_t origID); + + +/** + * delete a placeholder + * + * @param[in,out] placeholder address of the placeholder pointer + */ +void delete_placeholder( placeholder_param_t **placeholder); + +void insert_placeholder_into_list( placeholder_param_t *phld, placeholderlist_param_t *phldlist); + + +/** + * print placeholder parameters + * + * @param[in] phld placeholder pointer + */ +void print_placeholder( placeholder_param_t *phld); + + +/** + * print all placeholder parameters + * + * @param[in] list placeholder list pointer + */ +void print_allplaceholder( placeholderlist_param_t *list); + +#endif /* !PLACEHOLDER_MANAGER_H_ */ diff --git a/src/lib/openjpip/query_parser.c b/src/lib/openjpip/query_parser.c new file mode 100644 index 00000000..460a5eb6 --- /dev/null +++ b/src/lib/openjpip/query_parser.c @@ -0,0 +1,429 @@ +/* + * $Id: query_parser.c 53 2011-05-09 16:55:39Z kaori $ + * + * 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. + */ + + +#ifdef _WIN32 +#include <windows.h> +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#else +#include <strings.h> +#endif + +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include "query_parser.h" +#include "opj_stdint.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*/ + + +/** + * Get initialized query parameters + * + * @return initial query parameters + */ +query_param_t * get_initquery(void); + +/* + * get a pair of field name and value from the string starting fieldname=fieldval&... format + * + * @param[in] stringptr pointer to the beginning of the parsing string + * @param[out] fieldname string to copy the field name, if not found, NULL + * @param[out] fieldval string to copy the field value, if not found, NULL + * @return pointer to the next field string, if there is none, NULL + */ +char * get_fieldparam( const char *stringptr, char *fieldname, char *fieldval); + +void parse_cclose( char *src, query_param_t *query_param); +void parse_metareq( char *field, query_param_t *query_param); + +/* parse the requested components (parses forms like:a; a,b; a-b; a-b,c; a,b-c)*/ +void parse_comps( char *field, query_param_t *query_param); + + +/** maximum length of field name*/ +#define MAX_LENOFFIELDNAME 10 + +/** maximum length of field value*/ +#define MAX_LENOFFIELDVAL 128 + +query_param_t * parse_query( const char *query_string) +{ + query_param_t *query_param; + const char *pquery; + char fieldname[MAX_LENOFFIELDNAME], fieldval[MAX_LENOFFIELDVAL]; + + query_param = get_initquery(); + + pquery = query_string; + + while( pquery!=NULL) { + + pquery = get_fieldparam( pquery, fieldname, fieldval); + + if( fieldname[0] != '\0'){ + if( strcasecmp( fieldname, "target") == 0) + query_param->target = strdup( fieldval); + + else if( strcasecmp( fieldname, "tid") == 0) + query_param->tid = strdup( fieldval); + + else if( strcasecmp( fieldname, "fsiz") == 0) + sscanf( fieldval, "%d,%d", &query_param->fx, &query_param->fy); + + else if( strcasecmp( fieldname, "roff") == 0) + sscanf( fieldval, "%d,%d", &query_param->rx, &query_param->ry); + + 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) + query_param->cid = strdup( fieldval); + + else if( strcasecmp( fieldname, "cnew") == 0){ + if( strncasecmp( fieldval, "http-tcp", 8) == 0) + query_param->cnew = tcp; + else if( strncasecmp( fieldval, "http", 4) == 0) + query_param->cnew = http; + } + + else if( strcasecmp( fieldname, "cclose") == 0) + parse_cclose( fieldval, query_param); + + else if( strcasecmp( fieldname, "metareq") == 0) + parse_metareq( fieldval, query_param); + + else if( strcasecmp( fieldname, "comps") == 0) + parse_comps( fieldval, query_param); + + else if( strcasecmp( fieldname, "type") == 0){ + if( strncasecmp( fieldval, "jpp-stream", 10) == 0) + query_param->return_type = JPPstream; + 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); + if( query_param->len == 2000) /* for kakadu client*/ + strncpy( query_param->box_type[0], "ftyp", 4); + } + } + } + return query_param; +} + +query_param_t * get_initquery(void) +{ + query_param_t *query; + int i; + + query = (query_param_t *)malloc( sizeof(query_param_t)); + + query->target = NULL; + query->tid = NULL; + query->fx = -1; + query->fy = -1; + query->rx = -1; + query->ry = -1; + query->rw = -1; + query->rh = -1; + query->layers = -1; + query->lastcomp = -1; + query->comps = NULL; + query->cid = NULL; + query->cnew = non; + query->cclose = NULL; + query->numOfcclose = 0; + memset( query->box_type, 0, MAX_NUMOFBOX*4); + memset( query->limit, 0, MAX_NUMOFBOX*sizeof(int)); + for( i=0; i<MAX_NUMOFBOX; i++){ + query->w[i] = false; + query->s[i] = false; + query->g[i] = false; + query->a[i] = false; + query->priority[i] = false; + } + query->root_bin = 0; + query->max_depth = -1; + query->metadata_only = false; + query->return_type = UNKNOWN; + query->len = -1; + + return query; +} + + +char * get_fieldparam( const char *stringptr, char *fieldname, char *fieldval) +{ + char *eqp, *andp, *nexfieldptr; + + if((eqp = strchr( stringptr, '='))==NULL){ + fprintf( stderr, "= not found\n"); + strcpy( fieldname, ""); + strcpy( fieldval, ""); + return NULL; + } + if((andp = strchr( stringptr, '&'))==NULL){ + andp = strchr( stringptr, '\0'); + nexfieldptr = NULL; + } + else + nexfieldptr = andp+1; + + assert( (size_t)(eqp-stringptr)); + strncpy( fieldname, stringptr, (size_t)(eqp-stringptr)); + fieldname[eqp-stringptr]='\0'; + assert( andp-eqp-1 >= 0); + strncpy( fieldval, eqp+1, (size_t)(andp-eqp-1)); + fieldval[andp-eqp-1]='\0'; + + return nexfieldptr; +} + +void print_queryparam( query_param_t query_param) +{ + int i; + char *cclose; + + fprintf( logstream, "query parameters:\n"); + + if( query_param.target) + fprintf( logstream, "\t target: %s\n", query_param.target); + + if( query_param.tid) + 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"); + else{ + for( i=0; i<=query_param.lastcomp; i++) + if( query_param.comps[i]) + fprintf( logstream, "%d ", i); + fprintf( logstream, "\n"); + } + fprintf( logstream, "\t cnew: %d\n", query_param.cnew); + + if( query_param.cid) + fprintf( logstream, "\t cid: %s\n", query_param.cid); + + if( query_param.cclose){ + fprintf( logstream, "\t cclose: "); + + for( i=0, cclose=query_param.cclose; i<query_param.numOfcclose; i++){ + fprintf( logstream, "%s ", cclose); + cclose += (strlen(cclose)+1); + } + fprintf(logstream, "\n"); + } + + fprintf( logstream, "\t req-box-prop\n"); + for( i=0; query_param.box_type[i][0]!=0 && i<MAX_NUMOFBOX; i++){ + fprintf( logstream, "\t\t box_type: %.4s limit: %d w:%d s:%d g:%d a:%d priority:%d\n", query_param.box_type[i], query_param.limit[i], query_param.w[i], query_param.s[i], query_param.g[i], query_param.a[i], query_param.priority[i]); + } + + fprintf( logstream, "\t root-bin: %d\n", query_param.root_bin); + 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 parse_cclose( char *src, query_param_t *query_param) +{ + size_t i; + size_t len; + + len = strlen( src); + query_param->cclose = strdup( src); + + for( i=0; i<len; i++) + if( query_param->cclose[i] == ','){ + query_param->cclose[i] = '\0'; + query_param->numOfcclose ++; + } + + query_param->numOfcclose ++; +} + +void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param); + +void parse_metareq( char *field, query_param_t *query_param) +{ + char req_box_prop[20]; + char *ptr, *src; + int numofboxreq = 0; + + memset( req_box_prop, 0, 20); + + /* req-box-prop*/ + ptr = strchr( field, '['); + ptr++; + src = ptr; + while( *ptr != ']'){ + if( *ptr == ';'){ + assert( ptr-src >= 0); + strncpy( req_box_prop, src, (size_t)(ptr-src)); + parse_req_box_prop( req_box_prop, numofboxreq++, query_param); + ptr++; + src = ptr; + memset( req_box_prop, 0, 20); + } + ptr++; + } + assert(ptr-src>=0); + strncpy( req_box_prop, src, (size_t)(ptr-src)); + + parse_req_box_prop( req_box_prop, numofboxreq++, query_param); + + if(( ptr = strchr( field, 'R'))) + sscanf( ptr+1, "%d", &(query_param->root_bin)); + + if(( ptr = strchr( field, 'D'))) + sscanf( ptr+1, "%d", &(query_param->max_depth)); + + if(( ptr = strstr( field, "!!"))) + query_param->metadata_only = true; +} + +void parse_req_box_prop( char *req_box_prop, int idx, query_param_t *query_param) +{ + char *ptr; + + if( *req_box_prop == '*') + query_param->box_type[idx][0]='*'; + else + strncpy( query_param->box_type[idx], req_box_prop, 4); + + if(( ptr = strchr( req_box_prop, ':'))){ + if( *(ptr+1)=='r') + query_param->limit[idx] = -1; + else + sscanf( ptr+1, "%d", &(query_param->limit[idx])); + } + + if(( ptr = strchr( req_box_prop, '/'))){ + ptr++; + while( *ptr=='w' || *ptr=='s' || *ptr=='g' || *ptr=='a'){ + switch( *ptr){ + case 'w': query_param->w[idx] = true; break; + case 's': query_param->s[idx] = true; break; + case 'g': query_param->g[idx] = true; break; + case 'a': query_param->a[idx] = true; break; + } + ptr++; + } + } + else{ + query_param->g[idx] = true; + query_param->s[idx] = true; + query_param->w[idx] = true; + } + + if((ptr = strchr( req_box_prop, '!'))) + query_param->priority[idx] = true; + + idx++; +} + +void parse_comps( char *field, query_param_t *query_param) +{ + int i,start,stop,aux = -1; + char *ptr1,*ptr2; + + ptr1 = strchr( field, '-'); + ptr2 = strchr( field, ','); + + if( ptr1 && ptr2) + if( ptr1 > ptr2) + sscanf( field, "%d,%d-%d",&aux, &start, &stop); + else + sscanf( field, "%d-%d,%d", &start, &stop, &aux); + else + if(ptr1) + sscanf( field, "%d-%d", &start, &stop); + else if(ptr2){ + sscanf( field, "%d,%d", &start, &stop); + aux = start; + start = stop; + } + else{ + sscanf( field, "%d", &stop); + start = stop; + } + + query_param->lastcomp = stop > aux ? stop : aux; + query_param->comps = (bool *)calloc( 1, (OPJ_SIZE_T)(query_param->lastcomp+1)*sizeof(bool)); + + for( i=start; i<=stop; i++) + query_param->comps[i]=true; + + if(aux!=-1) + query_param->comps[aux] = true; +} + +void delete_query( query_param_t **query) +{ + if( (*query)->target) + free( (*query)->target); + + if( (*query)->tid) + free( (*query)->tid); + + if( (*query)->comps) + free((*query)->comps); + + if( (*query)->cid) + free( (*query)->cid); + + if( (*query)->cclose) + free( (*query)->cclose); + + free( *query); +} diff --git a/src/lib/openjpip/query_parser.h b/src/lib/openjpip/query_parser.h new file mode 100644 index 00000000..d60cafe6 --- /dev/null +++ b/src/lib/openjpip/query_parser.h @@ -0,0 +1,97 @@ +/* + * $Id: query_parser.h 53 2011-05-09 16:55:39Z kaori $ + * + * 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 QUERY_PARSER_H_ +# define QUERY_PARSER_H_ + +#include "bool.h" + +/** maximum number of meta request box */ +#define MAX_NUMOFBOX 10 + +/** cnew aux transport name */ +typedef enum cnew_transport { non, http, tcp, udp} cnew_transport_t; + +/** image return type */ +typedef enum image_return { JPPstream, JPTstream, UNKNOWN=-1} image_return_t; + +/** Query parameters */ +typedef struct query_param{ + char *target; /**< target name */ + char *tid; /**< 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 (dynamic array) for jpp-stream, null means all components */ + char *cid; /**< channel identifier */ + cnew_transport_t cnew; /**< transport name if there is new channel request, else non */ + char *cclose; /**< list of closing channel identifiers, separated by '\0' */ + int numOfcclose; /**< number of closing channels */ + char box_type[MAX_NUMOFBOX][4]; /**< interested box-types */ + int limit[MAX_NUMOFBOX]; /**< limit value, -1: skeleton request "r", 0: entire contents */ + bool w[MAX_NUMOFBOX]; /**< Metadata request qualifier flags */ + bool s[MAX_NUMOFBOX]; + bool g[MAX_NUMOFBOX]; + bool a[MAX_NUMOFBOX]; + bool priority[MAX_NUMOFBOX]; /**< priority flag */ + int root_bin; /**< root-bin */ + 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; + + +/** + * parse query + * + * @param[in] query_string request query string + * @return pointer to query parameters + */ +query_param_t * parse_query( const char *query_string); + +/** + * print query parameters + * + * @param[in] query_param query parameters + */ +void print_queryparam( query_param_t query_param); + + +/** + * delete query + * + * @param[in] query address of the deleting query pointer + */ +void delete_query( query_param_t **query); + +#endif /* !QUERY_PARSER_H_ */ diff --git a/src/lib/openjpip/session_manager.c b/src/lib/openjpip/session_manager.c new file mode 100644 index 00000000..5c1d7588 --- /dev/null +++ b/src/lib/openjpip/session_manager.c @@ -0,0 +1,196 @@ +/* + * $Id: session_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "session_manager.h" +#include "target_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 */ + + +sessionlist_param_t * gene_sessionlist(void) +{ + sessionlist_param_t *sessionlist; + + sessionlist = (sessionlist_param_t *)malloc( sizeof(sessionlist_param_t)); + + sessionlist->first = NULL; + sessionlist->last = NULL; + + return sessionlist; +} + +session_param_t * gene_session( sessionlist_param_t *sessionlist) +{ + session_param_t *session; + + session = (session_param_t *)malloc( sizeof(session_param_t)); + + session->channellist = gene_channellist(); + session->cachemodellist = gene_cachemodellist(); + + session->next = NULL; + + if( sessionlist->first) /* there are one or more entries */ + sessionlist->last->next = session; + else /* first entry */ + sessionlist->first = session; + sessionlist->last = session; + + return session; +} + +bool search_session_and_channel( char cid[], + sessionlist_param_t *sessionlist, + session_param_t **foundsession, + channel_param_t **foundchannel) +{ + *foundsession = sessionlist->first; + + while( *foundsession != NULL){ + + *foundchannel = (*foundsession)->channellist->first; + + while( *foundchannel != NULL){ + + if( strcmp( cid, (*foundchannel)->cid) == 0) + return true; + + *foundchannel = (*foundchannel)->next; + } + *foundsession = (*foundsession)->next; + } + + fprintf( FCGI_stdout, "Status: 503\r\n"); + fprintf( FCGI_stdout, "Reason: Channel %s not found\r\n", cid); + + return false; +} + +void insert_cachemodel_into_session( session_param_t *session, cachemodel_param_t *cachemodel) +{ + if(!cachemodel) + return; + +#ifndef SERVER + fprintf( logstream, "local log: insert cachemodel into session\n"); +#endif + if( session->cachemodellist->first != NULL) + session->cachemodellist->last->next = cachemodel; + else + session->cachemodellist->first = cachemodel; + session->cachemodellist->last = cachemodel; +} + +bool delete_session( session_param_t **session, sessionlist_param_t *sessionlist) +{ + session_param_t *ptr; + + if( *session == NULL) + return false; + + + if( *session == sessionlist->first) + sessionlist->first = (*session)->next; + else{ + ptr = sessionlist->first; + while( ptr->next != *session) + ptr = ptr->next; + ptr->next = (*session)->next; + + if( *session == sessionlist->last) + sessionlist->last = ptr; + } + + delete_channellist( &((*session)->channellist)); + delete_cachemodellist( &((*session)->cachemodellist)); + +#ifndef SERVER + fprintf( logstream, "local log: session: %p deleted!\n", (void *)(*session)); +#endif + free( *session); + + return true; +} + +void delete_sessionlist( sessionlist_param_t **sessionlist) +{ + session_param_t *sessionPtr, *sessionNext; + + sessionPtr = (*sessionlist)->first; + while( sessionPtr != NULL){ + sessionNext=sessionPtr->next; + + delete_channellist( &(sessionPtr->channellist)); + delete_cachemodellist( &(sessionPtr->cachemodellist)); + +#ifndef SERVER + fprintf( logstream, "local log: session: %p deleted!\n", (void *)sessionPtr); +#endif + free( sessionPtr); + + sessionPtr=sessionNext; + } + + (*sessionlist)->first = NULL; + (*sessionlist)->last = NULL; + + free(*sessionlist); +} + +void print_allsession( sessionlist_param_t *sessionlist) +{ + session_param_t *ptr; + cachemodel_param_t *cachemodel; + int i=0; + + fprintf( logstream, "SESSIONS info:\n"); + + ptr = sessionlist->first; + while( ptr != NULL){ + fprintf( logstream, "session No.%d\n", i++); + print_allchannel( ptr->channellist); + cachemodel = ptr->cachemodellist->first; + while( cachemodel){ + print_target( cachemodel->target); + cachemodel = cachemodel->next; + } + ptr=ptr->next; + } +} diff --git a/src/lib/openjpip/session_manager.h b/src/lib/openjpip/session_manager.h new file mode 100644 index 00000000..03df4f4b --- /dev/null +++ b/src/lib/openjpip/session_manager.h @@ -0,0 +1,116 @@ +/* + * $Id: session_manager.h 53 2011-05-09 16:55:39Z kaori $ + * + * 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. + */ + +#ifndef SESSION_MANAGER_H_ +# define SESSION_MANAGER_H_ + +#include "bool.h" +#include "channel_manager.h" +#include "cachemodel_manager.h" + +/** Session parameters*/ +typedef struct session_param{ + channellist_param_t *channellist; /**< channel list pointer*/ + cachemodellist_param_t *cachemodellist; /**< cache list pointer*/ + struct session_param *next; /**< pointer to the next session*/ +} session_param_t; + +/** Session list parameters*/ +typedef struct sessionlist_param{ + session_param_t *first; /**< first session pointer of the list*/ + session_param_t *last; /**< last session pointer of the list*/ +} sessionlist_param_t; + + +/** + * generate a session list + * + * @return pointer to the generated session list + */ +sessionlist_param_t * gene_sessionlist(void); + + +/** + * generate a session under the sesion list + * + * @param[in] sessionlist session list to insert the new session + * @return pointer to the generated session + */ +session_param_t * gene_session( sessionlist_param_t *sessionlist); + +/** + * search a channel and its belonging session by channel ID + * + * @param[in] cid channel identifier + * @param[in] sessionlist session list pointer + * @param[in,out] foundsession address of the found session pointer + * @param[in,out] foundchannel address of the found channel pointer + * @return if the channel is found (true) or not (false) + */ +bool search_session_and_channel( char cid[], + sessionlist_param_t *sessionlist, + session_param_t **foundsession, + channel_param_t **foundchannel); + +/** + * insert a cache model into a session + * + * @param[in] session session pointer + * @param[in] cachemodel cachemodel pointer + */ +void insert_cachemodel_into_session( session_param_t *session, cachemodel_param_t *cachemodel); + + +/** + * delete a session + * + * @param[in] session address of the session pointer + * @param[in] sessionlist session list pointer + * @return if succeeded (true) or failed (false) + */ +bool delete_session( session_param_t **session, sessionlist_param_t *sessionlist); + + +/** + * delete session list + * + * @param[in,out] sessionlist address of the session list pointer + */ +void delete_sessionlist( sessionlist_param_t **sessionlist); + +/** + * print all sessions + * + * @param[in] sessionlist session list pointer + */ +void print_allsession( sessionlist_param_t *sessionlist); + + +#endif /* !SESSION_MANAGER_H_ */ diff --git a/src/lib/openjpip/sock_manager.c b/src/lib/openjpip/sock_manager.c new file mode 100644 index 00000000..432b03fa --- /dev/null +++ b/src/lib/openjpip/sock_manager.c @@ -0,0 +1,181 @@ +/* + * $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. + */ + +#ifdef _WIN32 +#include <windows.h> +#else +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <unistd.h> +#endif + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "sock_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*/ + +SOCKET open_listeningsocket( uint16_t port) +{ + SOCKET listening_socket; + struct sockaddr_in sin; + int sock_optval = 1; + + listening_socket = socket(AF_INET, SOCK_STREAM, 0); + if ( listening_socket == -1 ){ + perror("socket"); + exit(1); + } + + if ( setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (const char *)&sock_optval, sizeof(sock_optval)) == -1 ){ + perror("setsockopt"); + exit(1); + } + + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + sin.sin_addr.s_addr = htonl(INADDR_ANY); + + if ( bind(listening_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0 ){ + perror("bind"); + close_socket(listening_socket); + exit(1); + } + + if( listen(listening_socket, SOMAXCONN) == -1){ + perror("listen"); + close_socket(listening_socket); + exit(1); + } + fprintf( FCGI_stderr, "port %d is listened\n", port); + + 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); +} + +void send_stream( SOCKET connected_socket, const void *stream, OPJ_SIZE_T length) +{ + char *ptr = (char*)stream; + OPJ_SIZE_T remlen = length; + + while( remlen > 0){ + ssize_t sentlen = send( connected_socket, ptr, remlen, 0); + if( sentlen == -1){ + fprintf( FCGI_stderr, "sending stream error\n"); + break; + } + remlen = remlen - (OPJ_SIZE_T)sentlen; + ptr = ptr + sentlen; + } +} + +void * receive_stream( SOCKET connected_socket, OPJ_SIZE_T length) +{ + char *stream, *ptr; + OPJ_SIZE_T remlen; + + ptr = stream = malloc( length); + remlen = length; + + while( remlen > 0){ + ssize_t redlen = recv( connected_socket, ptr, remlen, 0); + if( redlen == -1){ + fprintf( FCGI_stderr, "receive stream error\n"); + free( stream); + stream = NULL; + break; + } + remlen -= (OPJ_SIZE_T)redlen; + ptr = ptr + redlen; + } + return stream; +} + +OPJ_SIZE_T receive_line(SOCKET connected_socket, char *p) +{ + OPJ_SIZE_T len = 0; + while (1){ + ssize_t ret; + ret = recv( connected_socket, p, 1, 0); + if ( ret == -1 ){ + perror("receive"); + exit(1); + } else if ( ret == 0 ){ + break; + } + if ( *p == '\n' ) + break; + p++; + len++; + } + *p = '\0'; + + if( len == 0) + fprintf( FCGI_stderr, "Header receive error\n"); + + return len; +} + +char * receive_string( SOCKET connected_socket) +{ + char buf[BUF_LEN]; + + /* MM FIXME: there is a nasty bug here, size of buf if BUF_LEN which is never + indicated to downstream receive_line */ + receive_line( connected_socket, buf); + + return strdup(buf); +} + +int close_socket( SOCKET sock) +{ +#ifdef _WIN32 + return closesocket( sock); +#else + return close( sock); +#endif +} diff --git a/src/lib/openjpip/sock_manager.h b/src/lib/openjpip/sock_manager.h new file mode 100644 index 00000000..ee67131e --- /dev/null +++ b/src/lib/openjpip/sock_manager.h @@ -0,0 +1,106 @@ +/* + * $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. + */ + +#ifndef SOCK_MANAGER_H_ +# define SOCK_MANAGER_H_ + +#include "bool.h" +#include "byte_manager.h" +#include "opj_stdint.h" + +#ifdef _WIN32 +#include <winsock.h> +#else +typedef int SOCKET; +#endif /*_WIN32*/ + +#define BUF_LEN 256 + +/** + * open listening socket + * + * @param port opening port number + * @return new socket + */ +SOCKET open_listeningsocket( uint16_t port); + +/** + * 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); + + +/** + * receive a string line (ending with '\n') from client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [out] buf string to be stored + * @return red size + */ +OPJ_SIZE_T receive_line(SOCKET connected_socket, char *buf); + +/** + * receive a string line (ending with '\n') from client, return malloc string + * + * @param [in] connected_socket file descriptor of the connected socket + * @return pointer to the string (memory allocated) + */ +char * receive_string( SOCKET connected_socket); + +/** + * receive data stream to client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] length length of the receiving stream + * @return pointer to the data stream (memory allocated), NULL if failed + */ +void * receive_stream( SOCKET connected_socket, OPJ_SIZE_T length); + +/** + * send data stream to client + * + * @param [in] connected_socket file descriptor of the connected socket + * @param [in] stream data stream + * @param [in] length length of data stream + */ +void send_stream( SOCKET connected_socket, const void *stream, OPJ_SIZE_T length); + +/** + * close socket + * + * @param [in] sock closing socket + * @return 0 if succeed, -1 if failed + */ +int close_socket( SOCKET sock); + +#endif /* !SOCK_MANAGER_H_ */ diff --git a/src/lib/openjpip/target_manager.c b/src/lib/openjpip/target_manager.c new file mode 100644 index 00000000..8b4763a5 --- /dev/null +++ b/src/lib/openjpip/target_manager.c @@ -0,0 +1,345 @@ +/* + * $Id: target_manager.c 44 2011-02-15 12:32:29Z kaori $ + * + * 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 <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <assert.h> +#ifdef _WIN32 +#define snprintf _snprintf /* Visual Studio */ +#include <io.h> +#else +#include <sys/types.h> +#include <unistd.h> +#endif +#include <sys/stat.h> +#include <fcntl.h> +#include <time.h> +#include "target_manager.h" + +#ifdef SERVER +#include <curl/curl.h> +#include "fcgi_stdio.h" +#define logstream FCGI_stdout +#else +#define FCGI_stdout stdout +#define FCGI_stderr stderr +#define logstream stderr +#endif /*SERVER*/ + +targetlist_param_t * gene_targetlist(void) +{ + targetlist_param_t *targetlist; + + targetlist = (targetlist_param_t *)malloc( sizeof(targetlist_param_t)); + + targetlist->first = NULL; + targetlist->last = NULL; + + return targetlist; +} + + +/** + * open jp2 format image file + * + * @param[in] filepath file name (.jp2) + * @param[out] tmpfname new file name if filepath is a URL + * @return file descriptor + */ +int open_jp2file( const char filepath[], char tmpfname[]); + +target_param_t * gene_target( targetlist_param_t *targetlist, char *targetpath) +{ + target_param_t *target; + int fd; + index_param_t *jp2idx; + char tmpfname[MAX_LENOFTID]; + static int last_csn = 0; + + if( targetpath[0]=='\0'){ + fprintf( FCGI_stderr, "Error: exception, no targetpath in gene_target()\n"); + return NULL; + } + + if((fd = open_jp2file( targetpath, tmpfname)) == -1){ + fprintf( FCGI_stdout, "Status: 404\r\n"); + return NULL; + } + + if( !(jp2idx = parse_jp2file( fd))){ + fprintf( FCGI_stdout, "Status: 501\r\n"); + return NULL; + } + + target = (target_param_t *)malloc( sizeof(target_param_t)); + snprintf( target->tid, MAX_LENOFTID, "%x-%x", (unsigned int)time(NULL), (unsigned int)rand()); + target->targetname = strdup( targetpath); + target->fd = fd; +#ifdef SERVER + if( tmpfname[0]) + target->tmpfname = strdup( tmpfname); + else + target->tmpfname = NULL; +#endif + target->csn = last_csn++; + target->codeidx = jp2idx; + target->num_of_use = 0; + target->jppstream = true; + target->jptstream = isJPTfeasible( *jp2idx); + target->next=NULL; + + if( targetlist->first) /* there are one or more entries*/ + targetlist->last->next = target; + else /* first entry*/ + targetlist->first = target; + targetlist->last = target; + +#ifndef SERVER + fprintf( logstream, "local log: target %s generated\n", targetpath); +#endif + + return target; +} + +void refer_target( target_param_t *reftarget, target_param_t **ptr) +{ + *ptr = reftarget; + reftarget->num_of_use++; +} + +void unrefer_target( target_param_t *target) +{ + target->num_of_use--; +} + +void delete_target( target_param_t **target) +{ + close( (*target)->fd); + +#ifdef SERVER + if( (*target)->tmpfname){ + fprintf( FCGI_stderr, "Temporal file %s is deleted\n", (*target)->tmpfname); + remove( (*target)->tmpfname); + } +#endif + + if( (*target)->codeidx) + delete_index ( &(*target)->codeidx); + +#ifndef SERVER + fprintf( logstream, "local log: target: %s deleted\n", (*target)->targetname); +#endif + + free( (*target)->targetname); + + free(*target); +} + +void delete_target_in_list( target_param_t **target, targetlist_param_t *targetlist) +{ + target_param_t *ptr; + + if( *target == targetlist->first) + targetlist->first = (*target)->next; + else{ + ptr = targetlist->first; + while( ptr->next != *target){ + ptr=ptr->next; + } + + ptr->next = (*target)->next; + + if( *target == targetlist->last) + targetlist->last = ptr; + } + delete_target( target); +} + +void delete_targetlist(targetlist_param_t **targetlist) +{ + target_param_t *targetPtr, *targetNext; + + targetPtr = (*targetlist)->first; + while( targetPtr != NULL){ + targetNext=targetPtr->next; + delete_target( &targetPtr); + targetPtr=targetNext; + } + free( *targetlist); +} + +void print_target( target_param_t *target) +{ + fprintf( logstream, "target:\n"); + fprintf( logstream, "\t tid=%s\n", target->tid); + fprintf( logstream, "\t csn=%d\n", target->csn); + fprintf( logstream, "\t target=%s\n\n", target->targetname); +} + +void print_alltarget( targetlist_param_t *targetlist) +{ + target_param_t *ptr; + + ptr = targetlist->first; + while( ptr != NULL){ + print_target( ptr); + ptr=ptr->next; + } +} + +target_param_t * search_target( const char targetname[], targetlist_param_t *targetlist) +{ + target_param_t *foundtarget; + + foundtarget = targetlist->first; + + while( foundtarget != NULL){ + + if( strcmp( targetname, foundtarget->targetname) == 0) + return foundtarget; + + foundtarget = foundtarget->next; + } + return NULL; +} + +target_param_t * search_targetBytid( const char tid[], targetlist_param_t *targetlist) +{ + target_param_t *foundtarget; + + foundtarget = targetlist->first; + + while( foundtarget != NULL){ + + if( strcmp( tid, foundtarget->tid) == 0) + return foundtarget; + + foundtarget = foundtarget->next; + } + + return NULL; +} + +int open_remotefile( const char filepath[], char tmpfname[]); + +int open_jp2file( const char filepath[], char tmpfname[]) +{ + int fd; + char *data; + + /* download remote target file to local storage*/ + if( strncmp( filepath, "http://", 7) == 0){ + if( (fd = open_remotefile( filepath, tmpfname)) == -1) + return -1; + } + else{ + tmpfname[0] = 0; + if( (fd = open( filepath, O_RDONLY)) == -1){ + fprintf( FCGI_stdout, "Reason: Target %s not found\r\n", filepath); + return -1; + } + } + /* Check resource is a JP family file.*/ + if( lseek( fd, 0, SEEK_SET)==-1){ + close(fd); + fprintf( FCGI_stdout, "Reason: Target %s broken (lseek error)\r\n", filepath); + return -1; + } + + data = (char *)malloc( 12); /* size of header*/ + + if( read( fd, data, 12) != 12){ + free( data); + close(fd); + fprintf( FCGI_stdout, "Reason: Target %s broken (read error)\r\n", filepath); + return -1; + } + + if( *data || *(data + 1) || *(data + 2) || + *(data + 3) != 12 || strncmp (data + 4, "jP \r\n\x87\n", 8)){ + free( data); + close(fd); + fprintf( FCGI_stdout, "Reason: No JPEG 2000 Signature box in target %s\r\n", filepath); + return -1; + } + + free( data); + + return fd; +} + +#ifdef SERVER +static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream); +#endif + +int open_remotefile( const char filepath[], char tmpfname[]) +{ +#ifndef SERVER + (void)filepath; + (void)tmpfname; + fprintf( FCGI_stderr, "Remote file can not be opened in local mode\n"); + return -1; + +#else + + CURL *curl_handle; + int fd; + + curl_handle = curl_easy_init(); + curl_easy_setopt(curl_handle, CURLOPT_URL, filepath); + curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); + + snprintf( tmpfname, MAX_LENOFTID, "%x-%x.jp2", (unsigned int)time(NULL), (unsigned int)rand()); + fprintf( FCGI_stderr, "%s is downloaded to a temporal new file %s\n", filepath, tmpfname); + if( (fd = open( tmpfname, O_RDWR|O_CREAT|O_EXCL, S_IRWXU)) == -1){ + fprintf( FCGI_stdout, "Reason: File open error %s\r\n", tmpfname); + curl_easy_cleanup(curl_handle); + return -1; + } + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &fd); + curl_easy_perform(curl_handle); + curl_easy_cleanup(curl_handle); + + return fd; +#endif /*SERVER*/ +} + +#ifdef SERVER +static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) +{ + int *fd = (int *)stream; + ssize_t written = write( *fd, ptr, size*nmemb); + assert( written >= 0 ); + + return (size_t)written; +} +#endif /*SERVER*/ diff --git a/src/lib/openjpip/target_manager.h b/src/lib/openjpip/target_manager.h new file mode 100644 index 00000000..275adc4a --- /dev/null +++ b/src/lib/openjpip/target_manager.h @@ -0,0 +1,159 @@ +/* + * $Id: target_manager.h 44 2011-02-15 12:32:29Z kaori $ + * + * 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. + */ + +#ifndef TARGET_MANAGER_H_ +# define TARGET_MANAGER_H_ + +#include "bool.h" +#include "index_manager.h" + +/** maximum length of target identifier*/ +#define MAX_LENOFTID 30 + +/** target parameters*/ +typedef struct target_param{ + char tid[MAX_LENOFTID]; /**< target identifier*/ + char *targetname; /**< local file path or URL ( URL is suported only with SERVER mode)*/ + int fd; /**< file descriptor*/ +#ifdef SERVER + char *tmpfname; /**< temporal file name to download a remote target file*/ +#endif + int csn; /**< codestream number */ + index_param_t *codeidx; /**< index information of codestream */ + int num_of_use; /**< numbers of sessions refering to this target */ + bool jppstream; /**< if this target can return JPP-stream */ + bool jptstream; /**< if this target can return JPP-stream */ + struct target_param *next; /**< pointer to the next target */ +} target_param_t; + + +/** Target list parameters*/ +typedef struct targetlist_param{ + target_param_t *first; /**< first target pointer of the list*/ + target_param_t *last; /**< last target pointer of the list*/ +} targetlist_param_t; + + + +/** + * generate a target list + * + * @return pointer to the generated target list + */ +targetlist_param_t * gene_targetlist(void); + + +/** + * generate a target + * + * @param[in] targetlist target list to insert the generated target + * @param[in] targetpath file path or URL of the target + * @return pointer to the generated target + */ +target_param_t * gene_target( targetlist_param_t *targetlist, char *targetpath); + + +/** + * refer a target, used to make a new cache model + * + * @param[in] reftarget reference target pointer + * @param[out] ptr address of feeding target pointer + */ +void refer_target( target_param_t *reftarget, target_param_t **ptr); + + +/** + * refer a target, used to make a new cache model + * + * @param[in] target reference pointer to the target + */ +void unrefer_target( target_param_t *target); + +/** + * delete a target + * + * @param[in,out] target address of the deleting target pointer + */ +void delete_target( target_param_t **target); + + +/** + * delete a target in list + * + * @param[in,out] target address of the deleting target pointer + * @param[in] targetlist target list pointer + */ +void delete_target_in_list( target_param_t **target, targetlist_param_t *targetlist); + + +/** + * delete target list + * + * @param[in,out] targetlist address of the target list pointer + */ +void delete_targetlist(targetlist_param_t **targetlist); + + +/** + * print target parameters + * + * @param[in] target target pointer + */ +void print_target( target_param_t *target); + +/** + * print all target parameters + * + * @param[in] targetlist target list pointer + */ +void print_alltarget( targetlist_param_t *targetlist); + + +/** + * search a target by target name + * + * @param[in] targetname target name + * @param[in] targetlist target list pointer + * @return found target pointer + */ +target_param_t * search_target( const char targetname[], targetlist_param_t *targetlist); + + +/** + * search a target by tid + * + * @param[in] tid target identifier + * @param[in] targetlist target list pointer + * @return found target pointer + */ +target_param_t * search_targetBytid( const char tid[], targetlist_param_t *targetlist); + +#endif /* !TARGET_MANAGER_H_ */ + |
