1bc498a61a1097f6563f66f2efca7c0b98a8d7d8
[openjpeg.git] / src / lib / openjpip / msgqueue_manager.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  * Copyright (c) 2011,      Lucian Corlaciu, GSoC
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <assert.h>
39 #include <limits.h>
40 #ifdef _WIN32
41 #include <io.h>
42 #else
43 #include <unistd.h>
44 #endif
45 #include "msgqueue_manager.h"
46 #include "metadata_manager.h"
47 #include "index_manager.h"
48 #include "opj_inttypes.h"
49
50 #ifdef SERVER
51 #include "fcgi_stdio.h"
52 #define logstream FCGI_stdout
53 #else
54 #define FCGI_stdout stdout
55 #define FCGI_stderr stderr
56 #define logstream stderr
57 #endif /*SERVER*/
58
59 msgqueue_param_t * gene_msgqueue( bool stateless, cachemodel_param_t *cachemodel)
60 {
61   msgqueue_param_t *msgqueue;
62
63   msgqueue = (msgqueue_param_t *)opj_malloc( sizeof(msgqueue_param_t));
64
65   msgqueue->first = NULL;
66   msgqueue->last  = NULL;
67
68   msgqueue->stateless = stateless;
69   msgqueue->cachemodel = cachemodel;
70   
71   return msgqueue;
72 }
73
74 void delete_msgqueue( msgqueue_param_t **msgqueue)
75 {
76   message_param_t *ptr, *next;
77
78   if( !(*msgqueue))
79     return;
80   
81   ptr = (*msgqueue)->first;
82
83   while( ptr){
84     next = ptr->next;
85     opj_free( ptr);
86     ptr = next;
87   }
88   if( (*msgqueue)->stateless && (*msgqueue)->cachemodel)
89     delete_cachemodel( &((*msgqueue)->cachemodel));
90
91   opj_free(*msgqueue); 
92 }
93
94 void print_msgqueue( msgqueue_param_t *msgqueue)
95 {
96   message_param_t *ptr;
97   static const char *message_class[] = { "Precinct", "Ext-Prec", "TileHead", "non",
98     "Tile", "Ext-Tile", "Main", "non", "Meta"};
99
100   if( !msgqueue)
101     return;
102
103   fprintf( logstream, "message queue:\n");
104   ptr = msgqueue->first;
105
106   while( ptr){
107     fprintf( logstream, "\t class_id: %" PRId64 " %s\n", ptr->class_id, message_class[ptr->class_id]);
108     fprintf( logstream, "\t in_class_id: %" PRId64 "\n", ptr->in_class_id );
109     fprintf( logstream, "\t csn: %" PRId64 "\n", ptr->csn );
110     fprintf( logstream, "\t bin_offset: %#" PRIx64 "\n", ptr->bin_offset );
111     fprintf( logstream, "\t length: %#" PRIx64 "\n", ptr->length );
112     if( ptr->class_id%2)
113       fprintf( logstream, "\t aux: %" PRId64 "\n", ptr->aux );
114     fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte );
115     if( ptr->phld)
116       print_placeholder( ptr->phld);
117     else
118       fprintf( logstream, "\t res_offset: %#" PRIx64 "\n", ptr->res_offset );
119     fprintf( logstream, "\n");
120
121     ptr = ptr->next;
122   }
123 }
124
125 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue);
126
127 void enqueue_mainheader( msgqueue_param_t *msgqueue)
128 {
129   cachemodel_param_t *cachemodel;
130   target_param_t *target;
131   index_param_t *codeidx;
132   message_param_t *msg;
133
134   cachemodel = msgqueue->cachemodel;
135   target = cachemodel->target;
136   codeidx = target->codeidx;
137   
138   msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
139
140   msg->last_byte = true;
141   msg->in_class_id = 0;
142   msg->class_id = MAINHEADER_MSG;
143   assert( target->csn >= 0 );
144   msg->csn = (Byte8_t)target->csn;
145   msg->bin_offset = 0;
146   msg->length = codeidx->mhead_length;
147   msg->aux = 0; /* non exist*/
148   msg->res_offset = codeidx->offset;
149   msg->phld = NULL;
150   msg->next = NULL;
151
152   enqueue_message( msg, msgqueue);
153
154   cachemodel->mhead_model = true;
155 }
156
157 void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue)
158 {
159   cachemodel_param_t *cachemodel;
160   target_param_t *target;
161   index_param_t *codeidx;
162   message_param_t *msg;
163
164   cachemodel = msgqueue->cachemodel;
165   target = cachemodel->target;
166   codeidx = target->codeidx;
167
168   if( !cachemodel->th_model[ tile_id]){
169     msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
170     msg->last_byte = true;
171     assert( tile_id >= 0 );
172     msg->in_class_id = (Byte8_t)tile_id;
173     msg->class_id = TILE_HEADER_MSG;
174     assert( target->csn >= 0 );
175     msg->csn = (Byte8_t)target->csn;
176     msg->bin_offset = 0;
177     msg->length = codeidx->tileheader[tile_id]->tlen-2; /* SOT marker segment is removed*/
178     msg->aux = 0; /* non exist*/
179     msg->res_offset = codeidx->offset + (OPJ_OFF_T)get_elemOff(codeidx->tilepart, 0, (Byte8_t)tile_id) + 2; /* skip SOT marker seg*/
180     msg->phld = NULL;
181     msg->next = NULL;
182     
183     enqueue_message( msg, msgqueue);
184     cachemodel->th_model[ tile_id] = true;
185   }
186 }
187
188 void enqueue_tile( Byte4_t tile_id, int level, msgqueue_param_t *msgqueue)
189 {
190   cachemodel_param_t *cachemodel;
191   target_param_t *target;
192   bool *tp_model;
193   Byte8_t numOftparts; /* num of tile parts par tile*/
194   Byte8_t numOftiles;
195   index_param_t *codeidx;
196   faixbox_param_t *tilepart;
197   message_param_t *msg;
198   Byte8_t binOffset, binLength, class_id;
199   Byte8_t i;
200
201   cachemodel = msgqueue->cachemodel;
202   target = cachemodel->target;
203   codeidx  = target->codeidx;
204   tilepart = codeidx->tilepart;
205   
206   numOftparts = get_nmax( tilepart);
207   numOftiles  = get_m( tilepart);
208
209   class_id = (numOftparts==1) ? TILE_MSG : EXT_TILE_MSG;
210   
211   if( /*tile_id < 0 ||*/ numOftiles <= (Byte8_t)tile_id){
212     fprintf( FCGI_stderr, "Error, Invalid tile-id %d\n", tile_id);
213     return;
214   }
215   
216   tp_model = &cachemodel->tp_model[ tile_id*numOftparts];
217
218   binOffset=0;
219   for( i=0; i<numOftparts-(Byte8_t)level; i++){
220     binLength = get_elemLen( tilepart, i, tile_id);
221     
222     if( !tp_model[i]){
223       msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
224       
225       msg->last_byte = (i==numOftparts-1);
226       msg->in_class_id = tile_id;
227       msg->class_id = class_id;
228       assert( target->csn >= 0 );
229       msg->csn = (Byte8_t)target->csn;
230       msg->bin_offset = binOffset;
231       msg->length = binLength;
232       msg->aux = numOftparts-i;
233       msg->res_offset = codeidx->offset+(OPJ_OFF_T)get_elemOff( tilepart, i, tile_id)/*-1*/;
234       msg->phld = NULL;
235       msg->next = NULL;
236
237       enqueue_message( msg, msgqueue);
238
239       tp_model[i] = true;
240     }
241     binOffset += binLength;
242   }
243 }
244
245 void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue)
246 {
247   cachemodel_param_t *cachemodel;
248   index_param_t *codeidx;
249   faixbox_param_t *precpacket;
250   message_param_t *msg;
251   Byte8_t nmax, binOffset, binLength;
252   int layer_id, numOflayers;
253   
254   cachemodel = msgqueue->cachemodel;
255   codeidx = cachemodel->target->codeidx;
256   precpacket = codeidx->precpacket[ comp_id];
257   numOflayers = codeidx->COD.numOflayers;
258
259   nmax = get_nmax(precpacket);
260   assert( nmax < INT_MAX );
261   if( layers < 0)
262     layers = numOflayers;
263   assert( tile_id >= 0 );
264     
265   binOffset = 0;
266   for( layer_id = 0; layer_id < layers; layer_id++){
267
268     binLength = get_elemLen( precpacket, (Byte8_t)(seq_id*numOflayers+layer_id), (Byte8_t)tile_id);
269     
270     if( !cachemodel->pp_model[comp_id][tile_id*(int)nmax+seq_id*numOflayers+layer_id]){
271   
272       msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
273       msg->last_byte = (layer_id == (numOflayers-1));
274       msg->in_class_id = comp_precinct_id( tile_id, comp_id, seq_id, codeidx->SIZ.Csiz, (int)codeidx->SIZ.XTnum * (int) codeidx->SIZ.YTnum);
275       msg->class_id = PRECINCT_MSG;
276       msg->csn = (Byte8_t)cachemodel->target->csn;
277       msg->bin_offset = binOffset;
278       msg->length = binLength;
279       msg->aux = 0;
280       msg->res_offset = codeidx->offset+(OPJ_OFF_T)get_elemOff( precpacket, (Byte8_t)(seq_id*numOflayers+layer_id), (Byte8_t)tile_id);
281       msg->phld = NULL;
282       msg->next = NULL;
283
284       enqueue_message( msg, msgqueue);
285       
286       cachemodel->pp_model[comp_id][tile_id*(int)nmax+seq_id*numOflayers+layer_id] = true;
287     }
288     binOffset += binLength;
289   }
290 }
291
292 /* MM FIXME: each params is coded on int, this is really not clear from the specs what it should be */
293 Byte8_t comp_precinct_id( int t, int c, int s, int num_components, int num_tiles)
294 {
295   return (Byte8_t)(t + (c + s * num_components ) * num_tiles);
296 }
297
298 void enqueue_box(  Byte8_t meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
299 void enqueue_phld( Byte8_t meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
300 void enqueue_boxcontents( Byte8_t meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
301
302 void enqueue_metadata( Byte8_t meta_id, msgqueue_param_t *msgqueue)
303 {
304   metadatalist_param_t *metadatalist;
305   metadata_param_t *metadata;
306   Byte8_t binOffset;
307
308   metadatalist = msgqueue->cachemodel->target->codeidx->metadatalist;
309   metadata = search_metadata( meta_id, metadatalist);
310   
311   if( !metadata){
312     fprintf( FCGI_stderr, "Error: metadata-bin %" PRIu64 " not found\n", meta_id);
313     return;
314   }
315   binOffset = 0;
316   
317   if( metadata->boxlist)
318     enqueue_box( meta_id, metadata->boxlist, msgqueue, &binOffset);
319
320   if( metadata->placeholderlist)
321     enqueue_phld( meta_id, metadata->placeholderlist, msgqueue, &binOffset);
322
323   if( metadata->boxcontents)
324     enqueue_boxcontents( meta_id, metadata->boxcontents, msgqueue, &binOffset);
325   
326   msgqueue->last->last_byte = true;
327 }
328
329 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);
330
331 void enqueue_box( Byte8_t meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
332 {
333   box_param_t *box;
334   message_param_t *msg;
335   
336   box = boxlist->first;
337   assert( msgqueue->cachemodel->target->csn >= 0);
338   while( box){
339     msg = gene_metamsg( meta_id, *binOffset, box->length, box->offset, NULL, (Byte8_t)msgqueue->cachemodel->target->csn);
340     enqueue_message( msg, msgqueue);
341
342     *binOffset += box->length;
343     box = box->next;
344   }
345 }
346
347 void enqueue_phld( Byte8_t meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
348 {
349   placeholder_param_t *phld;
350   message_param_t *msg;
351   
352   phld = phldlist->first;
353   assert( msgqueue->cachemodel->target->csn >= 0);
354   while( phld){
355     msg = gene_metamsg( meta_id, *binOffset, phld->LBox, 0, phld, (Byte8_t)msgqueue->cachemodel->target->csn);
356     enqueue_message( msg, msgqueue);
357
358     *binOffset += phld->LBox;
359     phld = phld->next;
360   }
361 }
362
363 void enqueue_boxcontents( Byte8_t meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
364 {
365   message_param_t *msg;
366
367   assert(msgqueue->cachemodel->target->csn >= 0);
368   msg = gene_metamsg( meta_id, *binOffset, boxcontents->length,
369     boxcontents->offset, NULL, (Byte8_t)msgqueue->cachemodel->target->csn);
370   enqueue_message( msg, msgqueue);
371   
372   *binOffset += boxcontents->length;
373 }
374
375 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)
376 {
377   message_param_t *msg;
378
379   msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
380     
381   msg->last_byte = false;
382   msg->in_class_id = meta_id;
383   msg->class_id = METADATA_MSG;
384   msg->csn = csn;
385   msg->bin_offset = binOffset;
386   msg->length = length;
387   msg->aux = 0; /* non exist*/
388   msg->res_offset = res_offset;
389   msg->phld = phld;
390   msg->next = NULL;
391
392   return msg;
393 }
394
395 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue)
396 {
397   if( msgqueue->first)
398     msgqueue->last->next = msg;
399   else
400     msgqueue->first = msg;
401   
402   msgqueue->last = msg;
403 }
404
405 void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd);
406 void add_vbas_stream( Byte8_t code, int tmpfd);
407 void add_body_stream( message_param_t *msg, int fd, int tmpfd);
408 void add_placeholder_stream( placeholder_param_t *phld, int tmpfd);
409
410 void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd)
411 {
412   message_param_t *msg;
413   Byte8_t class_id, csn;
414   Byte_t bb, c;
415   
416   if( !(msgqueue))
417     return;
418
419   msg = msgqueue->first;
420   class_id = (Byte8_t)-1;
421   csn = (Byte8_t)-1;
422   while( msg){
423     if( msg->csn == csn){
424       if( msg->class_id == class_id)
425         bb = 1;
426       else{
427         bb = 2;
428         class_id = msg->class_id;
429       }
430     }
431     else{
432       bb = 3;
433       class_id = msg->class_id;
434       csn = msg->csn;
435     }
436
437     c = msg->last_byte ? 1 : 0;
438     
439     add_bin_id_vbas_stream( bb, c, msg->in_class_id, tmpfd);
440     
441     if( bb >= 2)
442       add_vbas_stream( class_id, tmpfd);
443     if (bb == 3)
444       add_vbas_stream( csn, tmpfd);
445     
446     add_vbas_stream( msg->bin_offset, tmpfd);
447     add_vbas_stream (msg->length, tmpfd);
448     
449     if( msg->class_id%2) /* Aux is present only if the id is odd*/
450       add_vbas_stream( msg->aux, tmpfd);
451
452     if( msg->phld)
453       add_placeholder_stream( msg->phld, tmpfd);
454     else
455       add_body_stream( msg, msgqueue->cachemodel->target->fd, tmpfd);
456
457     msg = msg->next;
458   }
459 }
460
461 void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd);
462 void print_binarycode( Byte8_t n, int segmentlen);
463
464 void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd)
465 {
466   int bytelength;
467   Byte8_t tmp;
468
469   /* A.2.3 In-class identifiers */
470   /* 7k-3bits, where k is the number of bytes in the VBAS*/
471   bytelength = 1;
472   tmp = in_class_id >> 4;
473   while( tmp){
474     bytelength ++;
475     tmp >>= 7;
476   }
477
478   in_class_id |= (Byte8_t)((((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7));
479   
480   add_vbas_with_bytelen_stream( in_class_id, bytelength, tmpfd);
481 }
482
483 void add_vbas_stream( Byte8_t code, int tmpfd)
484 {
485   int bytelength;
486   Byte8_t tmp;
487
488   bytelength = 1;
489   tmp = code;
490   while( tmp >>= 7)
491     bytelength ++;
492
493   add_vbas_with_bytelen_stream( code, bytelength, tmpfd);
494 }
495
496 void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd)
497 {
498   int n;
499   Byte8_t seg;
500   
501   n = bytelength - 1;
502   while( n >= 0) {
503     seg = ( code >> (n*7)) & 0x7f;
504     if( n)
505       seg |= 0x80;
506     if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
507       fprintf( FCGI_stderr, "Error: failed to write vbas\n");
508       return;
509     }
510     n--;
511   }
512 }
513
514 void add_body_stream( message_param_t *msg, int fd, int tmpfd)
515 {
516   Byte_t *data;
517
518   if( !(data = fetch_bytes( fd, msg->res_offset, msg->length))){
519     fprintf( FCGI_stderr, "Error: fetch_bytes in add_body_stream()\n");
520     return;
521   }
522
523   if( write( tmpfd, data, msg->length) < 1){
524     opj_free( data);
525     fprintf( FCGI_stderr, "Error: fwrite in add_body_stream()\n");
526     return;
527   }
528   opj_free(data);
529 }
530
531 void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd);
532
533 void add_placeholder_stream( placeholder_param_t *phld, int tmpfd)
534 {
535   add_bigendian_bytestream( phld->LBox, 4, tmpfd);
536   if( write( tmpfd, phld->TBox, 4) < 1){
537     fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
538     return;
539   }
540   add_bigendian_bytestream( phld->Flags, 4, tmpfd);
541   add_bigendian_bytestream( phld->OrigID, 8, tmpfd);
542
543   if( write( tmpfd, phld->OrigBH, phld->OrigBHlen) < 1){
544     fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
545     return;
546   }
547 }
548
549 void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd)
550 {
551   int n;
552   Byte8_t seg;
553   
554   n = bytelength - 1;
555   while( n >= 0) {
556     seg = ( code >> (n*8)) & 0xff;
557     if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
558       fprintf( FCGI_stderr, "ERROR: failed to write bigendian_bytestream\n");
559       return;
560     }
561     n--;
562   }
563 }
564
565 void print_binarycode( Byte8_t n, int segmentlen)
566 {
567   char buf[256];
568   int i=0, j, k;
569
570   do{
571     buf[i++] = n%2 ? '1' : '0';
572   }while((n=n/2));
573
574   for( j=segmentlen-1; j>=i; j--)
575     putchar('0');
576   
577   for( j=i-1, k=0; j>=0; j--, k++){
578     putchar( buf[j]);
579     if( !((k+1)%segmentlen))
580       printf(" ");
581   }
582   printf("\n");
583 }
584
585 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id);
586 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem);
587
588 void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, OPJ_OFF_T offset, msgqueue_param_t *msgqueue)
589 {
590   Byte_t *ptr;  /* stream pointer*/
591   message_param_t *msg;
592   Byte_t bb, c;
593   Byte8_t class_id, csn;
594
595   class_id = (Byte8_t)-1; /* dummy*/
596   csn = (Byte8_t)-1;
597   ptr = JPIPstream;
598   while( (Byte8_t)(ptr-JPIPstream) < streamlen){
599     msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
600     
601     ptr = parse_bin_id_vbas( ptr, &bb, &c, &msg->in_class_id);
602     
603     msg->last_byte   = c == 1 ? true : false;
604     
605     if( bb >= 2)
606       ptr = parse_vbas( ptr, &class_id);
607
608     msg->class_id = class_id;
609     
610     if (bb == 3)
611       ptr = parse_vbas( ptr, &csn);
612     msg->csn = csn;
613     
614     ptr = parse_vbas( ptr, &msg->bin_offset);
615     ptr = parse_vbas( ptr, &msg->length);
616     
617     if( msg->class_id%2) /* Aux is present only if the id is odd*/
618       ptr = parse_vbas( ptr, &msg->aux);
619     else
620       msg->aux = 0;
621     
622     msg->res_offset = ptr-JPIPstream+offset;
623     msg->phld = NULL;
624     msg->next = NULL;
625
626     if(msgqueue->first)
627       msgqueue->last->next = msg;
628     else
629       msgqueue->first = msg;
630     msgqueue->last = msg;
631     
632     ptr += msg->length;
633   }
634 }
635
636 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *stream);
637
638 void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist)
639 {
640   message_param_t *msg;
641   (void)streamlen;
642
643   if( metadatalist == NULL)
644     return;
645   
646   msg = msgqueue->first;
647   while( msg){
648     if( msg->class_id == METADATA_MSG){
649       metadata_param_t *metadata = gene_metadata( msg->in_class_id, NULL, NULL, NULL);
650       insert_metadata_into_list( metadata, metadatalist);
651       parse_metadata( metadata, msg, stream+msg->res_offset);
652     }
653     msg = msg->next;
654   }
655 }
656
657 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength);
658
659 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *datastream)
660 {
661   box_param_t *box;
662   placeholder_param_t *phld;
663   char *boxtype = (char *)(datastream+4);
664
665   msg->phld = NULL;
666
667   if( strncmp( boxtype, "phld", 4) == 0){
668     if( !metadata->placeholderlist)
669         metadata->placeholderlist = gene_placeholderlist();
670     
671     phld = parse_phld( datastream, msg->length);
672     msg->phld = phld;
673     insert_placeholder_into_list( phld, metadata->placeholderlist);
674   }
675   else if( isalpha(boxtype[0]) && isalpha(boxtype[1]) &&
676            (isalnum(boxtype[2])||isspace(boxtype[2])) &&
677            (isalpha(boxtype[3])||isspace(boxtype[3]))){
678     if( !metadata->boxlist)
679       metadata->boxlist = gene_boxlist();
680     
681     box = gene_boxbyOffinStream( datastream, msg->res_offset);
682     insert_box_into_list( box, metadata->boxlist);
683   }
684   else
685     metadata->boxcontents = gene_boxcontents( msg->res_offset, msg->length);
686 }
687
688 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength)
689 {
690   placeholder_param_t *phld;
691
692   phld = (placeholder_param_t *)opj_malloc( sizeof(placeholder_param_t));
693   
694   phld->LBox = big4( datastream);
695   strcpy( phld->TBox, "phld");
696   phld->Flags = big4( datastream+8);
697   phld->OrigID = big8( datastream+12);
698   phld->OrigBHlen = (Byte_t)(metalength - 20);
699   phld->OrigBH = (Byte_t *)opj_malloc(phld->OrigBHlen);
700   memcpy( phld->OrigBH, datastream+20, phld->OrigBHlen);
701   phld->next = NULL;
702
703   return phld;
704 }
705
706 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id)
707 {
708   Byte_t code;
709   Byte_t *ptr;
710
711   ptr = streamptr;
712   code = *(ptr++);
713
714   *bb = (code >> 5) & 3;
715   *c  = (code >> 4) & 1;
716   
717   *in_class_id = code & 15;
718
719   while(code >> 7){
720     code = *(ptr++);
721     *in_class_id = (*in_class_id << 7) | (code & 0x7f);
722   }
723   return ptr;
724 }
725
726 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem)
727 {
728   Byte_t code;
729   Byte_t *ptr;
730   
731   *elem = 0;
732   ptr = streamptr;
733   do{
734     code = *(ptr++);
735     *elem = (*elem << 7) | (code & 0x7f);
736   }while(code >> 7);
737   
738   return ptr;
739 }
740
741 void delete_message_in_msgqueue( message_param_t **msg, msgqueue_param_t *msgqueue)
742 {
743   message_param_t *ptr;
744
745   if( !(*msg))
746     return;
747
748   if( *msg == msgqueue->first)
749     msgqueue->first = (*msg)->next;
750   else{
751     ptr = msgqueue->first;
752     while( ptr->next != *msg){
753       ptr=ptr->next;
754     }
755     
756     ptr->next = (*msg)->next;
757     
758     if( *msg == msgqueue->last)
759       msgqueue->last = ptr;
760   }
761   opj_free( *msg);
762 }