[1.5][JPIP] fixed Region of Interest option, and memory leak of opj_dec_server
[openjpeg.git] / applications / jpip / libopenjpip / openjpip.c
1 /*
2  * $Id$
3  *
4  * Copyright (c) 2002-2011, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium
5  * Copyright (c) 2002-2011, Professor Benoit Macq
6  * Copyright (c) 2010-2011, Kaori Hagihara
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <stdlib.h>
32 #include "openjpip.h"
33 #include "jpip_parser.h"
34 #include "channel_manager.h"
35
36 #include <stdio.h>
37 #include "dec_clientmsg_handler.h"
38 #include "jpipstream_manager.h"
39
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <unistd.h>
45 #include "jp2k_encoder.h"
46
47 server_record_t * init_JPIPserver()
48 {
49   server_record_t *record = (server_record_t *)malloc( sizeof(server_record_t));
50   
51   record->sessionlist = gene_sessionlist();
52   record->targetlist  = gene_targetlist();
53   
54   return record;
55 }
56
57 void terminate_JPIPserver( server_record_t **rec)
58 {
59   delete_sessionlist( &(*rec)->sessionlist);
60   delete_targetlist( &(*rec)->targetlist);
61
62   free( *rec);
63 }
64
65 QR_t * parse_querystring( char *query_string)
66 {
67   QR_t *qr;
68
69   qr = (QR_t *)malloc( sizeof(QR_t));
70     
71   qr->query = parse_query( query_string);
72   
73   qr->msgqueue = NULL;
74
75   return qr;
76 }
77
78 bool process_JPIPrequest( server_record_t *rec, QR_t *qr)
79 {
80   target_param_t *target = NULL;
81   session_param_t *cursession = NULL;
82   channel_param_t *curchannel = NULL;
83
84   if( qr->query->target[0] != '\0' || qr->query->tid[0] != '\0'){
85     if( !identify_target( *(qr->query), rec->targetlist, &target))
86       return false;
87   }
88
89   if( qr->query->cid[0] != '\0'){
90     if( !associate_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel))
91       return false;
92   }
93
94   if( qr->query->cnew){
95     if( !open_channel( *(qr->query), rec->sessionlist, target, &cursession, &curchannel))
96       return false;
97   }
98   if( qr->query->cclose[0][0] != '\0')
99     if( !close_channel( *(qr->query), rec->sessionlist, &cursession, &curchannel))
100       return false;
101   
102   if( (qr->query->fx > 0 && qr->query->fy > 0) || qr->query->box_type[0][0] != 0)
103     if( !gene_JPIPstream( *(qr->query), target, cursession, curchannel, &qr->msgqueue))
104       return false;
105   
106   return true;
107 }
108
109 void send_responsedata( QR_t *qr)
110 {
111   // Currently HTTP support only, find a way for TCP, UDP case
112   emit_stream_from_msgqueue( qr->msgqueue);
113 }
114
115 void end_QRprocess( server_record_t *rec, QR_t **qr)
116 {
117   // TODO: record client preferences if necessary
118   
119   delete_query( &((*qr)->query));
120   delete_msgqueue( &((*qr)->msgqueue));
121   free( *qr);
122 }
123
124 void local_log( bool query, bool messages, bool sessions, bool targets, QR_t *qr, server_record_t *rec)
125 {
126   if( query)
127     print_queryparam( *qr->query);
128
129   if( messages)
130     print_msgqueue( qr->msgqueue);
131
132   if( sessions)
133     print_allsession( rec->sessionlist);
134   
135   if( targets)
136     print_alltarget( rec->targetlist);
137 }
138
139 #ifndef SERVER
140
141 dec_server_record_t * init_dec_server()
142 {
143   dec_server_record_t *record = (dec_server_record_t *)malloc( sizeof(dec_server_record_t));
144
145   record->cachelist = gene_cachelist();
146   record->jpipstream = NULL;
147   record->jpipstreamlen = 0;
148   record->msgqueue = gene_msgqueue( true, NULL);
149   record->listening_socket = open_listeningsocket();
150
151   return record;
152 }
153
154 void terminate_dec_server( dec_server_record_t **rec)
155 {
156   delete_cachelist( &(*rec)->cachelist);  
157   free( (*rec)->jpipstream);
158   
159   if( (*rec)->msgqueue)
160     delete_msgqueue( &((*rec)->msgqueue));
161
162   if( close_socket( (*rec)->listening_socket) != 0)
163     perror("close");
164   
165   free( *rec);
166 }
167
168 client_t accept_connection( dec_server_record_t *rec)
169 {
170   client_t client;
171   
172   client = accept_socket( rec->listening_socket);
173   if( client == -1)
174     fprintf( stderr, "error: failed to connect to client\n");
175   
176   return client;
177 }
178
179 bool handle_clientreq( client_t client, dec_server_record_t *rec)
180 {
181   bool quit = false;
182   msgtype_t msgtype = identify_clientmsg( client);
183   
184   switch( msgtype){
185   case JPIPSTREAM:
186     handle_JPIPstreamMSG( client, rec->cachelist, &rec->jpipstream, &rec->jpipstreamlen, rec->msgqueue);
187     break;
188       
189   case PNMREQ:
190     handle_PNMreqMSG( client, rec->jpipstream, rec->msgqueue, rec->cachelist);
191     break;
192     
193   case XMLREQ:
194     handle_XMLreqMSG( client, rec->jpipstream, rec->cachelist);
195     break;
196
197   case TIDREQ:
198     handle_TIDreqMSG( client, rec->cachelist);
199     break;
200                                                 
201   case CIDREQ:
202     handle_CIDreqMSG( client, rec->cachelist);
203     break;
204
205   case CIDDST:
206     handle_dstCIDreqMSG( client, rec->cachelist);
207     break;
208     
209   case SIZREQ:
210     handle_SIZreqMSG( client, rec->jpipstream, rec->msgqueue, rec->cachelist);
211     break;
212
213   case JP2SAVE:
214     handle_JP2saveMSG( client, rec->cachelist, rec->msgqueue, rec->jpipstream);
215     break;
216
217   case QUIT:
218     quit = true;
219     save_codestream( rec->jpipstream, rec->jpipstreamlen, "jpt");
220     break;
221   case MSGERROR:
222     break;
223   }
224         
225   fprintf( stderr, "\t end of the connection\n\n");
226   if( close_socket(client) != 0){
227     perror("close");
228     return false;
229   }
230   if( quit)
231     return false;
232
233   return true;
234 }
235
236
237 jpip_dec_param_t * init_jpipdecoder( bool jp2)
238 {
239   jpip_dec_param_t *dec;
240   
241   dec = (jpip_dec_param_t *)calloc( 1, sizeof(jpip_dec_param_t));
242
243   dec->msgqueue = gene_msgqueue( true, NULL);
244   
245   if( jp2)
246     dec->metadatalist = gene_metadatalist();
247
248   return dec;
249 }
250
251
252 bool fread_jpip( char fname[], jpip_dec_param_t *dec)
253 {
254   int infd;
255   struct stat sb;
256
257   if(( infd = open( fname, O_RDONLY)) == -1){
258     fprintf( stderr, "file %s not exist\n", fname);
259     return false;
260   }
261   
262   if( fstat( infd, &sb) == -1){
263     fprintf( stderr, "input file stream is broken\n");
264     return false;
265   }
266   dec->jpiplen = (Byte8_t)sb.st_size;
267
268   dec->jpipstream = (Byte_t *)malloc( dec->jpiplen);
269
270   if( read( infd, dec->jpipstream, dec->jpiplen) != dec->jpiplen){
271     fprintf( stderr, "file reading error\n");
272     free( dec->jpipstream);
273     return false;
274   }
275
276   close(infd);
277
278   return true;
279 }
280
281 void decode_jpip( jpip_dec_param_t *dec)
282 {
283   parse_JPIPstream( dec->jpipstream, dec->jpiplen, 0, dec->msgqueue);
284
285   if( dec->metadatalist){ // JP2 encoding
286     parse_metamsg( dec->msgqueue, dec->jpipstream, dec->jpiplen, dec->metadatalist);
287     dec->ihdrbox = gene_ihdrbox( dec->metadatalist, dec->jpipstream);
288     
289     dec->jp2kstream = recons_jp2( dec->msgqueue, dec->jpipstream, dec->msgqueue->first->csn, &dec->jp2klen);
290   }
291   else // J2k encoding  
292     // Notice: arguments fw, fh need to be set for LRCP, PCRL, CPRL
293     dec->jp2kstream = recons_j2k( dec->msgqueue, dec->jpipstream, dec->msgqueue->first->csn, 0, 0, &dec->jp2klen);  
294 }
295
296 bool fwrite_jp2k( char fname[], jpip_dec_param_t *dec)
297 {
298   int outfd;
299   
300 #ifdef _WIN32
301   if(( outfd = open( fname, O_WRONLY|O_CREAT, _S_IREAD | _S_IWRITE)) == -1){
302 #else
303  if(( outfd = open( fname, O_WRONLY|O_CREAT, S_IRWXU|S_IRWXG)) == -1){
304 #endif
305    fprintf( stderr, "file %s open error\n", fname);
306    return false;
307  }
308   
309  if( write( outfd, dec->jp2kstream, dec->jp2klen) != dec->jp2klen)
310    fprintf( stderr, "j2k file write error\n");
311
312  close(outfd);
313
314  return true;
315 }
316
317 void output_log( bool messages, bool metadata, bool ihdrbox, jpip_dec_param_t *dec)
318 {
319   if( messages)
320     print_msgqueue( dec->msgqueue);
321
322   if( metadata)
323     print_allmetadata( dec->metadatalist);
324
325   if( ihdrbox){
326     printf("W*H: %d*%d\n", dec->ihdrbox->height, dec->ihdrbox->width);
327     printf("NC: %d, bpc: %d\n", dec->ihdrbox->nc, dec->ihdrbox->bpc);
328   }
329 }
330
331 void destroy_jpipdecoder( jpip_dec_param_t **dec)
332 {
333   free( (*dec)->jpipstream);
334   delete_msgqueue( &(*dec)->msgqueue);
335   if( (*dec)->metadatalist){
336     delete_metadatalist( &(*dec)->metadatalist);
337     free( (*dec)->ihdrbox);
338   }
339
340   free( (*dec)->jp2kstream);
341   free( *dec);
342 }
343
344 index_t * get_index_from_JP2file( int fd)
345 {
346   char *data;
347  
348   // Check resource is a JP family file.
349   if( lseek( fd, 0, SEEK_SET)==-1){
350     fprintf( stderr, "Error: File broken (lseek error)\n");
351     return NULL;
352   }
353   
354   data = (char *)malloc( 12); // size of header
355   if( read( fd, data, 12) != 12){
356     free( data);
357     fprintf( stderr, "Error: File broken (read error)\n");
358     return NULL;
359   }
360     
361   if( *data || *(data + 1) || *(data + 2) ||
362       *(data + 3) != 12 || strncmp (data + 4, "jP  \r\n\x87\n", 8)){
363     free( data);
364     fprintf( stderr, "Error: No JPEG 2000 Signature box in this file\n");
365     return NULL;
366   }
367   free( data);
368   
369   return parse_jp2file( fd);
370 }
371
372 void destroy_index( index_t **idx)
373 {
374   delete_index( idx);
375 }
376
377 void output_index( index_t *index)
378 {
379   print_index( *index);
380 }
381
382 #endif //SERVER