changed parameter and file names regarding JPT-stream to JPIP-stream, which handles...
[openjpeg.git] / applications / jpip / libopenjpip / msgqueue_manager.c
1 /*
2  * $Id: msgqueue_manager.c 53 2011-05-09 16:55:39Z kaori $
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 <math.h>
33 #include <sys/types.h>
34 #include <unistd.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "msgqueue_manager.h"
40 #include "metadata_manager.h"
41
42
43 #ifdef SERVER
44 #include "fcgi_stdio.h"
45 #define logstream FCGI_stdout
46 #else
47 #define FCGI_stdout stdout
48 #define FCGI_stderr stderr
49 #define logstream stderr
50 #endif //SERVER
51
52 #define TILE_MSG 4
53 #define EXT_TILE_MSG 5
54 #define MAINHEADER_MSG 6
55 #define METADATA_MSG 8
56
57 msgqueue_param_t * gene_msgqueue( bool stateless, target_param_t *target)
58 {
59   msgqueue_param_t *msgqueue;
60
61   msgqueue = (msgqueue_param_t *)malloc( sizeof(msgqueue_param_t));
62
63   msgqueue->first = NULL;
64   msgqueue->last  = NULL;
65
66   msgqueue->stateless = stateless;
67   msgqueue->target = target;
68   
69   return msgqueue;
70 }
71
72 void delete_msgqueue( msgqueue_param_t **msgqueue)
73 {
74   message_param_t *ptr, *next;
75
76   if( !(*msgqueue))
77     return;
78   
79   ptr = (*msgqueue)->first;
80
81   while( ptr){
82     next = ptr->next;
83     free( ptr);
84     ptr = next;
85   }
86   if( (*msgqueue)->stateless && (*msgqueue)->target)
87     delete_target( &((*msgqueue)->target));
88
89   free(*msgqueue); 
90 }
91
92 void print_msgqueue( msgqueue_param_t *msgqueue)
93 {
94   message_param_t *ptr;
95
96   if( !msgqueue)
97     return;
98
99   fprintf( logstream, "message queue:\n");
100   ptr = msgqueue->first;
101
102   while( ptr){
103     fprintf( logstream, "\t class_id: %lld\n", ptr->class_id );
104     fprintf( logstream, "\t in_class_id: %lld\n", ptr->in_class_id );
105     fprintf( logstream, "\t csn: %lld\n", ptr->csn );
106     fprintf( logstream, "\t bin_offset: %#llx\n", ptr->bin_offset );
107     fprintf( logstream, "\t length: %#llx\n", ptr->length );
108     fprintf( logstream, "\t aux: %lld\n", ptr->aux );
109     fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte );
110     if( ptr->phld)
111       print_placeholder( ptr->phld);
112     else
113       fprintf( logstream, "\t res_offset: %#llx\n", ptr->res_offset );
114     fprintf( logstream, "\n");
115
116     ptr = ptr->next;
117   }
118 }
119
120 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue);
121
122 void enqueue_mainheader( msgqueue_param_t *msgqueue)
123 {
124   target_param_t *target;
125   message_param_t *msg;
126
127   target = msgqueue->target;
128
129   msg = (message_param_t *)malloc( sizeof(message_param_t));
130
131   msg->last_byte = true;
132   msg->in_class_id = 0;
133   msg->class_id = MAINHEADER_MSG;
134   msg->csn = target->csn;
135   msg->bin_offset = 0;
136   msg->length = target->codeidx->mhead_length;
137   msg->aux = 0; // non exist
138   msg->res_offset = target->codeidx->offset;
139   msg->phld = NULL;
140   msg->next = NULL;
141
142   enqueue_message( msg, msgqueue);
143
144   target->codeidx->mhead_model = true;
145 }
146
147 void enqueue_tile( int tile_id, int level, msgqueue_param_t *msgqueue)
148 {
149   target_param_t *target;
150   bool *tp_model;
151   Byte8_t numOftparts; // num of tile parts par tile
152   Byte8_t numOftiles;
153   index_param_t *codeidx;
154   faixbox_param_t *tilepart;
155   message_param_t *msg;
156   Byte8_t binOffset, binLength;
157   int i;
158
159   target = msgqueue->target;
160   codeidx  = target->codeidx;
161   tilepart = codeidx->tilepart;
162   
163   numOftparts = get_nmax( tilepart);
164   numOftiles  = get_m( tilepart);
165
166   if( tile_id < 0 || numOftiles <= tile_id){
167     fprintf( FCGI_stderr, "Error, Invalid tile-id %d\n", tile_id);
168     return;
169   }
170   
171   tp_model = &codeidx->tp_model[ tile_id*numOftparts];
172   
173   binOffset=0;
174   for( i=0; i<numOftparts-level; i++){
175     binLength = get_elemLen( tilepart, i, tile_id);
176     
177     if( !tp_model[i]){
178       msg = (message_param_t *)malloc( sizeof(message_param_t));
179       
180       msg->last_byte = i==numOftparts-1? true : false;
181       msg->in_class_id = tile_id;
182 #if 0
183       msg->class_id = TILE_MSG;
184 #else
185       msg->class_id = EXT_TILE_MSG;
186 #endif
187       msg->csn = target->csn;
188       msg->bin_offset = binOffset;
189       msg->length = binLength;
190       msg->aux = numOftparts-i;
191       msg->res_offset = codeidx->offset+get_elemOff( tilepart, i, tile_id)/*-1*/;
192       msg->phld = NULL;
193       msg->next = NULL;
194
195       enqueue_message( msg, msgqueue);
196
197       tp_model[i] = true;
198     }
199     binOffset += binLength;
200   }
201 }
202
203 void enqueue_box(  int meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
204 void enqueue_phld( int meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
205 void enqueue_boxcontents( int meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
206
207 void enqueue_metadata( int meta_id, msgqueue_param_t *msgqueue)
208 {
209   metadatalist_param_t *metadatalist;
210   metadata_param_t *metadata;
211   Byte8_t binOffset;
212
213   metadatalist = msgqueue->target->codeidx->metadatalist;
214   metadata = search_metadata( meta_id, metadatalist);
215   
216   if( !metadata){
217     fprintf( FCGI_stderr, "Error: metadata-bin %d not found\n", meta_id);
218     return;
219   }
220   binOffset = 0;
221   
222   if( metadata->boxlist)
223     enqueue_box( meta_id, metadata->boxlist, msgqueue, &binOffset);
224
225   if( metadata->placeholderlist)
226     enqueue_phld( meta_id, metadata->placeholderlist, msgqueue, &binOffset);
227
228   if( metadata->boxcontents)
229     enqueue_boxcontents( meta_id, metadata->boxcontents, msgqueue, &binOffset);
230   
231   msgqueue->last->last_byte = true;
232 }
233
234 message_param_t * gene_metamsg( int meta_id, Byte8_t binoffset, Byte8_t length, Byte8_t res_offset, placeholder_param_t *phld, Byte8_t csn);
235
236 void enqueue_box( int meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
237 {
238   box_param_t *box;
239   message_param_t *msg;
240   
241   box = boxlist->first;
242   while( box){
243     msg = gene_metamsg( meta_id, *binOffset, box->length, box->offset, NULL, msgqueue->target->csn);
244     enqueue_message( msg, msgqueue);
245
246     *binOffset += box->length;
247     box = box->next;
248   }
249 }
250
251 void enqueue_phld( int meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
252 {
253   placeholder_param_t *phld;
254   message_param_t *msg;
255   
256   phld = phldlist->first;
257   while( phld){
258     msg = gene_metamsg( meta_id, *binOffset, phld->LBox, 0, phld, msgqueue->target->csn);
259     enqueue_message( msg, msgqueue);
260
261     *binOffset += phld->LBox;
262     phld = phld->next;
263   }
264 }
265
266 void enqueue_boxcontents( int meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
267 {
268   message_param_t *msg;
269
270   msg = gene_metamsg( meta_id, *binOffset, boxcontents->length, boxcontents->offset, NULL, msgqueue->target->csn);
271   enqueue_message( msg, msgqueue);
272   
273   *binOffset += boxcontents->length;
274 }
275
276 message_param_t * gene_metamsg( int meta_id, Byte8_t binOffset, Byte8_t length, Byte8_t res_offset, placeholder_param_t *phld, Byte8_t csn)
277 {
278   message_param_t *msg;
279
280   msg = (message_param_t *)malloc( sizeof(message_param_t));
281     
282   msg->last_byte = false;
283   msg->in_class_id = meta_id;
284   msg->class_id = METADATA_MSG;
285   msg->csn = csn;
286   msg->bin_offset = binOffset;
287   msg->length = length;
288   msg->aux = 0; // non exist
289   msg->res_offset = res_offset;
290   msg->phld = phld;
291   msg->next = NULL;
292
293   return msg;
294 }
295
296 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue)
297 {
298   if( msgqueue->first)
299     msgqueue->last->next = msg;
300   else
301     msgqueue->first = msg;
302   
303   msgqueue->last = msg;
304 }
305
306
307 void emit_bin_id_vbas( Byte_t bb, Byte_t c, Byte8_t in_class_id);
308 void emit_vbas( Byte8_t code);
309 void emit_body( message_param_t *msg, int fd);
310 void emit_placeholder( placeholder_param_t *phld);
311
312 void emit_stream_from_msgqueue( msgqueue_param_t *msgqueue)
313 {
314   message_param_t *msg;
315   Byte8_t class_id, csn;
316   Byte_t bb, c;
317   
318   if( !(msgqueue))
319     return;
320
321   msg = msgqueue->first;
322   class_id = 0;
323   csn = 0;
324   while( msg){
325     if( msg->csn == csn){
326       if( msg->class_id == class_id)
327         bb = 1;
328       else{
329         bb = 2;
330         class_id = msg->class_id;
331       }
332     }
333     else{
334       bb = 3;
335       class_id = msg->class_id;
336       csn = msg->csn;
337     }
338
339     c = msg->last_byte ? 1 : 0;
340       
341     emit_bin_id_vbas( bb, c, msg->in_class_id);
342     
343     if( bb >= 2)
344       emit_vbas( class_id);
345     if (bb == 3)
346       emit_vbas( csn);
347     
348     emit_vbas( msg->bin_offset);
349     emit_vbas (msg->length);
350     
351     if( msg->class_id%2) // Aux is present only if the id is odd
352       emit_vbas( msg->aux);
353
354     if( msg->phld)
355       emit_placeholder( msg->phld);
356     else
357       emit_body( msg, msgqueue->target->fd);
358
359     msg = msg->next;
360   }
361 }
362
363 void emit_vbas_with_bytelen( Byte8_t code, int bytelength);
364 void print_binarycode( Byte8_t n, int segmentlen);
365
366 void emit_bin_id_vbas( Byte_t bb, Byte_t c, Byte8_t in_class_id)
367 {
368   int bytelength;
369   Byte8_t tmp;
370
371   // A.2.3 In-class identifiers 
372   // 7k-3bits, where k is the number of bytes in the VBAS
373   bytelength = 1;
374   tmp = in_class_id >> 4;
375   while( tmp){
376     bytelength ++;
377     tmp >>= 7;
378   }
379
380   in_class_id |= (((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7);
381   
382   emit_vbas_with_bytelen( in_class_id, bytelength);
383 }
384
385 void emit_vbas( Byte8_t code)
386 {
387   int bytelength;
388   Byte8_t tmp;
389
390   bytelength = 1;
391   tmp = code;
392   while( tmp >>= 7)
393     bytelength ++;
394
395   emit_vbas_with_bytelen( code, bytelength);
396 }
397
398 void emit_vbas_with_bytelen( Byte8_t code, int bytelength)
399 {
400   int n;
401   Byte8_t seg;
402   
403   n = bytelength - 1;
404   while( n >= 0) {
405     seg = ( code >> (n*7)) & 0x7f;
406     if( n)
407       seg |= 0x80;
408     fputc(( Byte4_t)seg, FCGI_stdout);
409     n--;
410   }
411 }
412
413 void emit_body( message_param_t *msg, int fd)
414 {
415   Byte_t *data;
416
417   if( lseek( fd, msg->res_offset, SEEK_SET)==-1){
418     fprintf( FCGI_stderr, "Error: fseek in emit_body()\n");
419     return;
420   }
421   
422   data = (Byte_t *)malloc( msg->length);
423   if( read( fd, data, msg->length) != msg->length){
424     free( data);
425     fprintf( FCGI_stderr, "Error: fread in emit_body()\n");
426     return;
427   }
428
429   if( fwrite( data, msg->length, 1, FCGI_stdout) < 1){
430     free( data);
431     fprintf( FCGI_stderr, "Error: fwrite in emit_body()\n");
432     return;
433   }
434   free(data);
435 }
436
437 void emit_bigendian_bytes( Byte8_t code, int bytelength);
438
439 void emit_placeholder( placeholder_param_t *phld)
440 {
441   emit_bigendian_bytes( phld->LBox, 4);
442   if( fwrite( phld->TBox, 4, 1, FCGI_stdout) < 1){
443     fprintf( FCGI_stderr, "Error: fwrite in emit_placeholder()\n");
444     return;
445   }
446   emit_bigendian_bytes( phld->Flags, 4);
447   emit_bigendian_bytes( phld->OrigID, 8);
448
449   if( fwrite( phld->OrigBH, phld->OrigBHlen, 1, FCGI_stdout) < 1){
450     fprintf( FCGI_stderr, "Error: fwrite in emit_placeholder()\n");
451     return;
452   }
453 }
454
455 void emit_bigendian_bytes( Byte8_t code, int bytelength)
456 {
457   int n;
458   Byte8_t seg;
459   
460   n = bytelength - 1;
461   while( n >= 0) {
462     seg = ( code >> (n*8)) & 0xff;
463     fputc(( Byte4_t)seg, FCGI_stdout);
464     n--;
465   }
466 }
467 void print_binarycode( Byte8_t n, int segmentlen)
468 {
469   char buf[256];
470   int i=0, j, k;
471
472   do{
473     buf[i++] = n%2 ? '1' : '0';
474   }while((n=n/2));
475
476   for( j=segmentlen-1; j>=i; j--)
477     putchar('0');
478   
479   for( j=i-1, k=0; j>=0; j--, k++){
480     putchar( buf[j]);
481     if( !((k+1)%segmentlen))
482       printf(" ");
483   }
484   printf("\n");
485 }
486
487 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id);
488 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem);
489
490 void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, Byte8_t offset, msgqueue_param_t *msgqueue)
491 {
492   Byte_t *ptr;  // stream pointer
493   message_param_t *msg;
494   Byte_t bb, c;
495   Byte8_t class_id, csn;
496
497   class_id = -1; // dummy
498   csn = 0;
499   ptr = JPIPstream;
500   while( ptr-JPIPstream < streamlen){
501     msg = (message_param_t *)malloc( sizeof(message_param_t));
502     
503     ptr = parse_bin_id_vbas( ptr, &bb, &c, &msg->in_class_id);
504     
505     msg->last_byte   = c == 1 ? true : false;
506     
507     if( bb >= 2){
508       ptr = parse_vbas( ptr, &class_id);
509       //      fprintf( stdout, "class_id: %lld\n", class_id);
510     }
511     msg->class_id = class_id;
512     
513     if (bb == 3)
514       ptr = parse_vbas( ptr, &csn);
515     msg->csn = csn;
516     
517     ptr = parse_vbas( ptr, &msg->bin_offset);
518     ptr = parse_vbas( ptr, &msg->length);
519     
520     if( msg->class_id%2) // Aux is present only if the id is odd
521       ptr = parse_vbas( ptr, &msg->aux);
522     else
523       msg->aux = 0;
524     
525     msg->res_offset = ptr-JPIPstream+offset;   
526     msg->phld = NULL;
527     msg->next = NULL;
528
529     if(msgqueue->first)
530       msgqueue->last->next = msg;
531     else
532       msgqueue->first = msg;
533     msgqueue->last = msg;
534     
535     ptr += msg->length;
536   }
537 }
538
539 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *stream);
540
541 void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist)
542 {
543   message_param_t *msg;
544
545   if( metadatalist == NULL)
546     return;
547   
548   msg = msgqueue->first;
549   while( msg){
550     if( msg->class_id == METADATA_MSG){
551       metadata_param_t *metadata = gene_metadata( msg->in_class_id, NULL, NULL, NULL);
552       insert_metadata_into_list( metadata, metadatalist);
553       parse_metadata( metadata, msg, stream+msg->res_offset);
554     }
555     msg = msg->next;
556   }
557 }
558
559 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength);
560
561 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *datastream)
562 {
563   char *boxtype = (char *)(datastream+4);
564
565   msg->phld = NULL;
566
567   if( strncmp( boxtype, "phld", 4) == 0){
568     if( !metadata->placeholderlist)
569         metadata->placeholderlist = gene_placeholderlist();
570     
571     placeholder_param_t *phld = parse_phld( datastream, msg->length);
572     msg->phld = phld;
573     insert_placeholder_into_list( phld, metadata->placeholderlist);
574   }
575   else if( isalpha(boxtype[0]) && isalpha(boxtype[1]) &&
576            (isalnum(boxtype[2])||isblank(boxtype[2])) &&
577            (isalpha(boxtype[3])||isblank(boxtype[3]))){
578     if( !metadata->boxlist)
579       metadata->boxlist = gene_boxlist();
580     
581     box_param_t *box = gene_boxbyOffinStream( datastream, msg->res_offset);
582     insert_box_into_list( box, metadata->boxlist);
583   }
584   else
585     metadata->boxcontents = gene_boxcontents( msg->res_offset, msg->length);
586 }
587
588 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength)
589 {
590   placeholder_param_t *phld;
591
592   phld = (placeholder_param_t *)malloc( sizeof(placeholder_param_t));
593   
594   phld->LBox = big4( datastream);
595   strcpy( phld->TBox, "phld");
596   phld->Flags = big4( datastream+8);
597   phld->OrigID = big8( datastream+12);
598   phld->OrigBHlen = metalength - 20;
599   phld->OrigBH = (Byte_t *)malloc(phld->OrigBHlen);
600   memcpy( phld->OrigBH, datastream+20, phld->OrigBHlen);
601   phld->next = NULL;
602
603   return phld;
604 }
605
606 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id)
607 {
608   Byte_t code;
609   Byte_t *ptr;
610
611   ptr = streamptr;
612   code = *(ptr++);
613
614   *bb = (code >> 5) & 3;
615   *c  = (code >> 4) & 1;
616   
617   *in_class_id = code & 15;
618
619   while(code >> 7){
620     code = *(ptr++);
621     *in_class_id = (*in_class_id << 7) | (code & 0x7f);
622   }
623   return ptr;
624 }
625
626 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem)
627 {
628   Byte_t code;
629   Byte_t *ptr;
630   
631   *elem = 0;
632   ptr = streamptr;
633   do{
634     code = *(ptr++);
635     *elem = (*elem << 7) | (code & 0x7f);
636   }while(code >> 7);
637   
638   return ptr;
639 }
640
641 /**
642  * search a message by class_id
643  *
644  * @param[in] class_id    class identifiers 
645  * @param[in] in_class_id in-class identifiers, -1 means any
646  * @param[in] csn         codestream number
647  * @param[in] msg         first message pointer of the searching list
648  * @return                found message pointer
649  */
650 message_param_t * search_message( Byte8_t class_id, Byte8_t in_class_id, Byte8_t csn, message_param_t *msg);
651
652
653 /**
654  * delete a message in msgqueue
655  *
656  * @param[in] message  address of the deleting message pointer
657  * @param[in] msgqueue message queue pointer
658  */
659 void delete_message_in_msgqueue( message_param_t **message, msgqueue_param_t *msgqueue);
660
661 Byte_t * recons_codestream( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t csn, int minlev, Byte8_t *codelen);
662
663 // usable only to JPT-stream messages
664 Byte_t * recons_j2k( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t csn, int minlev, Byte8_t *j2klen)
665 {
666   Byte_t *j2kstream = NULL;
667   
668   if( !msgqueue)
669     return NULL;
670   
671   j2kstream = recons_codestream( msgqueue, stream, csn, minlev, j2klen);
672
673   return j2kstream;
674 }
675
676 Byte_t * add_emptyboxstream( placeholder_param_t *phld, Byte_t *jp2stream, Byte8_t *jp2len);
677 Byte_t * add_msgstream( message_param_t *message, Byte_t *origstream, Byte_t *j2kstream, Byte8_t *j2klen);
678
679 Byte_t * recons_jp2( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t csn, Byte8_t *jp2len)
680 {
681   message_param_t *ptr;
682   Byte_t *jp2stream = NULL;
683   Byte_t *codestream = NULL;
684   Byte8_t codelen;
685   Byte8_t jp2cDBoxOffset = 0, jp2cDBoxlen = 0;
686   
687   *jp2len = 0;
688
689   if( !msgqueue)
690     return NULL;
691     
692   ptr = msgqueue->first;
693   while(( ptr = search_message( METADATA_MSG, -1, csn, ptr))!=NULL){
694     if( ptr->phld){
695       if( strncmp( (char *)ptr->phld->OrigBH+4, "jp2c", 4) == 0){
696         jp2cDBoxOffset = *jp2len + ptr->phld->OrigBHlen;
697         jp2stream = add_emptyboxstream( ptr->phld, jp2stream, jp2len); // header only
698         jp2cDBoxlen = *jp2len - jp2cDBoxOffset;
699       }
700       else
701         jp2stream = add_emptyboxstream( ptr->phld, jp2stream, jp2len); // header only
702     }
703     jp2stream = add_msgstream( ptr, stream, jp2stream, jp2len);
704     ptr = ptr->next;
705   }
706   
707   codestream = recons_codestream( msgqueue, stream, csn, 0, &codelen);
708   
709   if( jp2cDBoxOffset != 0 && codelen <= jp2cDBoxlen)
710     memcpy( jp2stream+jp2cDBoxOffset, codestream, codelen);
711
712   free( codestream);
713   
714   return jp2stream;
715 }
716
717 int get_last_tileID( msgqueue_param_t *msgqueue, Byte8_t csn);
718 Byte_t * add_emptytilestream( const int tileID, Byte_t *j2kstream, Byte8_t *j2klen);
719 Byte_t * add_EOC( Byte_t *j2kstream, Byte8_t *j2klen);
720
721 Byte_t * recons_codestream( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t csn, int minlev, Byte8_t *codelen)
722 {
723   message_param_t *ptr;
724   Byte_t *codestream = NULL;
725   int last_tileID;
726   int tileID;
727   
728   *codelen = 0;
729
730   // main header first
731   ptr = msgqueue->first;
732   while(( ptr = search_message( MAINHEADER_MSG, -1, csn, ptr))!=NULL){
733     codestream = add_msgstream( ptr, stream, codestream, codelen);
734     ptr = ptr->next;
735   }
736
737   last_tileID = get_last_tileID( msgqueue, csn); 
738   
739   for( tileID=0; tileID <= last_tileID; tileID++){
740     bool found = false;
741     ptr = msgqueue->first;
742     while(( ptr = search_message( TILE_MSG, tileID, csn, ptr))!=NULL){
743       found = true;
744       codestream = add_msgstream( ptr, stream, codestream, codelen);
745       ptr = ptr->next;
746     }
747     ptr = msgqueue->first;
748     while(( ptr = search_message( EXT_TILE_MSG, tileID, csn, ptr))!=NULL){
749       if( ptr->aux >= minlev){
750         found = true;
751         codestream = add_msgstream( ptr, stream, codestream, codelen);
752       }
753       ptr = ptr->next;
754     }
755     if(!found)
756       codestream = add_emptytilestream( tileID, codestream, codelen);
757   }
758   codestream = add_EOC( codestream, codelen);
759   
760   return codestream;
761 }
762
763 int get_last_tileID( msgqueue_param_t *msgqueue, Byte8_t csn)
764 {
765   int last_tileID = 0;
766   message_param_t *msg;
767   
768   msg = msgqueue->first;
769   while( msg){
770     if((msg->class_id == TILE_MSG || msg->class_id == EXT_TILE_MSG) && msg->csn == csn && last_tileID < msg->in_class_id)
771       last_tileID = msg->in_class_id;
772     msg = msg->next;
773   }
774   return last_tileID;
775 }
776
777 message_param_t * search_message( Byte8_t class_id, Byte8_t in_class_id, Byte8_t csn, message_param_t *msg)
778 {
779   while( msg != NULL){
780     if( in_class_id == -1){
781       if( msg->class_id == class_id && msg->csn == csn)
782         return msg;
783     }
784     else{
785       if( msg->class_id == class_id && msg->in_class_id == in_class_id && msg->csn == csn)
786         return msg;
787     }
788     msg = msg->next;
789   }
790   return NULL;
791 }
792
793 void delete_message_in_msgqueue( message_param_t **msg, msgqueue_param_t *msgqueue)
794 {
795   message_param_t *ptr;
796
797   if( !(*msg))
798     return;
799
800   if( *msg == msgqueue->first)
801     msgqueue->first = (*msg)->next;
802   else{
803     ptr = msgqueue->first;
804     while( ptr->next != *msg){
805       ptr=ptr->next;
806     }
807     
808     ptr->next = (*msg)->next;
809     
810     if( *msg == msgqueue->last)
811       msgqueue->last = ptr;
812   }
813   free( *msg);
814 }
815
816 Byte_t * gene_msgstream( message_param_t *message, Byte_t *stream, Byte8_t *length);
817 Byte_t * gene_emptytilestream( const int tileID, Byte8_t *length);
818
819
820 Byte_t * add_msgstream( message_param_t *message, Byte_t *origstream, Byte_t *j2kstream, Byte8_t *j2klen)
821 {
822   Byte_t *newstream;
823   Byte8_t newlen;
824   Byte_t *buf;
825
826   if( !message)
827     return NULL;
828
829   newstream = gene_msgstream( message, origstream, &newlen);
830
831   buf = (Byte_t *)malloc(( *j2klen)+newlen);
832
833   memcpy( buf, j2kstream, *j2klen);
834   memcpy( buf+(*j2klen), newstream, newlen);
835   
836   *j2klen += newlen;
837   
838   free( newstream);
839   if(j2kstream) free(j2kstream);
840
841   return buf;
842 }
843  
844
845 Byte_t * add_emptyboxstream( placeholder_param_t *phld, Byte_t *jp2stream, Byte8_t *jp2len)
846 {
847   Byte_t *newstream;
848   Byte8_t newlen;
849   Byte_t *buf;
850   
851   if( phld->OrigBHlen == 8)
852     newlen = big4(phld->OrigBH);
853   else
854     newlen = big8(phld->OrigBH+8);
855
856   newstream = (Byte_t *)malloc( newlen);
857   memset( newstream, 0, newlen);
858   memcpy( newstream, phld->OrigBH, phld->OrigBHlen);
859
860   buf = (Byte_t *)malloc(( *jp2len)+newlen);
861
862   memcpy( buf, jp2stream, *jp2len);
863   memcpy( buf+(*jp2len), newstream, newlen);
864   
865   *jp2len += newlen;
866   
867   free( newstream);
868   if(jp2stream) free(jp2stream);
869
870   return buf;
871 }
872
873 Byte_t * add_emptytilestream( const int tileID, Byte_t *j2kstream, Byte8_t *j2klen)
874 {
875   Byte_t *newstream;
876   Byte8_t newlen;
877   Byte_t *buf;
878
879   newstream = gene_emptytilestream( tileID, &newlen);
880
881   buf = (Byte_t *)malloc(( *j2klen)+newlen);
882
883   memcpy( buf, j2kstream, *j2klen);
884   memcpy( buf+(*j2klen), newstream, newlen);
885   
886   *j2klen += newlen;
887
888   free( newstream);
889   if(j2kstream) free(j2kstream);
890
891   return buf;
892 }
893
894 Byte_t * add_EOC( Byte_t *j2kstream, Byte8_t *j2klen)
895 {
896   Byte2_t EOC = 0xd9ff;
897
898   Byte_t *buf;
899
900   buf = (Byte_t *)malloc(( *j2klen)+2);
901
902   memcpy( buf, j2kstream, *j2klen);
903   memcpy( buf+(*j2klen), &EOC, 2);
904
905   *j2klen += 2;
906
907   if(j2kstream) free(j2kstream);
908
909   return buf;
910 }
911
912 Byte_t * gene_msgstream( message_param_t *message, Byte_t *stream, Byte8_t *length)
913 {
914   Byte_t *buf;
915
916   if( !message)
917     return NULL;
918
919   *length = message->length;
920   buf = (Byte_t *)malloc( *length);
921   memcpy( buf, stream+message->res_offset,  *length);
922
923   return buf;
924 }
925
926 Byte_t * gene_emptytilestream( const int tileID, Byte8_t *length)
927 {
928   Byte_t *buf;
929   const Byte2_t SOT = 0x90ff;
930   const Byte2_t Lsot = 0xa << 8;
931   Byte2_t Isot;
932   const Byte4_t Psot = 0xe << 24;
933   const Byte_t TPsot = 0, TNsot = 0;
934   const Byte2_t SOD = 0x93ff;
935
936   *length = 14;
937   buf = (Byte_t *)malloc(*length);
938
939   Isot = tileID << 8;
940   
941   memcpy( buf, &SOT, 2);
942   memcpy( buf+2, &Lsot, 2);
943   memcpy( buf+4, &Isot, 2);
944   memcpy( buf+6, &Psot, 4);
945   memcpy( buf+10, &TPsot, 1);
946   memcpy( buf+11, &TNsot, 1);
947   memcpy( buf+12, &SOD, 2);
948
949   return buf;
950 }