295c2360cc843c1a5dbacf10e0a99b9b15afc184
[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  * 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 <unistd.h>
36 #include <sys/stat.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "msgqueue_manager.h"
40 #include "metadata_manager.h"
41 #include "index_manager.h"
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 msgqueue_param_t * gene_msgqueue( bool stateless, cachemodel_param_t *cachemodel)
53 {
54   msgqueue_param_t *msgqueue;
55
56   msgqueue = (msgqueue_param_t *)malloc( sizeof(msgqueue_param_t));
57
58   msgqueue->first = NULL;
59   msgqueue->last  = NULL;
60
61   msgqueue->stateless = stateless;
62   msgqueue->cachemodel = cachemodel;
63   
64   return msgqueue;
65 }
66
67 void delete_msgqueue( msgqueue_param_t **msgqueue)
68 {
69   message_param_t *ptr, *next;
70
71   if( !(*msgqueue))
72     return;
73   
74   ptr = (*msgqueue)->first;
75
76   while( ptr){
77     next = ptr->next;
78     free( ptr);
79     ptr = next;
80   }
81   if( (*msgqueue)->stateless && (*msgqueue)->cachemodel)
82     delete_cachemodel( &((*msgqueue)->cachemodel));
83
84   free(*msgqueue); 
85 }
86
87 void print_msgqueue( msgqueue_param_t *msgqueue)
88 {
89   message_param_t *ptr;
90   char *message_class[] = { "Precinct", "Ext-Prec", "TileHead", "non", "Tile", "Ext-Tile", "Main", "non", "Meta"};
91
92   if( !msgqueue)
93     return;
94
95   fprintf( logstream, "message queue:\n");
96   ptr = msgqueue->first;
97
98   while( ptr){
99     fprintf( logstream, "\t class_id: %lld %s\n", ptr->class_id, message_class[ptr->class_id]);
100     fprintf( logstream, "\t in_class_id: %lld\n", ptr->in_class_id );
101     fprintf( logstream, "\t csn: %lld\n", ptr->csn );
102     fprintf( logstream, "\t bin_offset: %#llx\n", ptr->bin_offset );
103     fprintf( logstream, "\t length: %#llx\n", ptr->length );
104     if( ptr->class_id%2)
105       fprintf( logstream, "\t aux: %lld\n", ptr->aux );
106     fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte );
107     if( ptr->phld)
108       print_placeholder( ptr->phld);
109     else
110       fprintf( logstream, "\t res_offset: %#llx\n", ptr->res_offset );
111     fprintf( logstream, "\n");
112
113     ptr = ptr->next;
114   }
115 }
116
117 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue);
118
119 void enqueue_mainheader( msgqueue_param_t *msgqueue)
120 {
121   cachemodel_param_t *cachemodel;
122   target_param_t *target;
123   index_param_t *codeidx;
124   message_param_t *msg;
125
126   cachemodel = msgqueue->cachemodel;
127   target = cachemodel->target;
128   codeidx = target->codeidx;
129   
130   msg = (message_param_t *)malloc( sizeof(message_param_t));
131
132   msg->last_byte = true;
133   msg->in_class_id = 0;
134   msg->class_id = MAINHEADER_MSG;
135   msg->csn = target->csn;
136   msg->bin_offset = 0;
137   msg->length = codeidx->mhead_length;
138   msg->aux = 0; // non exist
139   msg->res_offset = codeidx->offset;
140   msg->phld = NULL;
141   msg->next = NULL;
142
143   enqueue_message( msg, msgqueue);
144
145   cachemodel->mhead_model = true;
146 }
147
148 void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue)
149 {
150   cachemodel_param_t *cachemodel;
151   target_param_t *target;
152   index_param_t *codeidx;
153   message_param_t *msg;
154
155   cachemodel = msgqueue->cachemodel;
156   target = cachemodel->target;
157   codeidx = target->codeidx;
158
159   if( !cachemodel->th_model[ tile_id]){
160     msg = (message_param_t *)malloc( sizeof(message_param_t));
161     msg->last_byte = true;
162     msg->in_class_id = tile_id;
163     msg->class_id = TILE_HEADER_MSG;
164     msg->csn = target->csn;
165     msg->bin_offset = 0;
166     msg->length = codeidx->tileheader[tile_id]->tlen-2; // SOT marker segment is removed
167     msg->aux = 0; // non exist
168     msg->res_offset = codeidx->offset + get_elemOff( codeidx->tilepart, 0, tile_id) + 2; // skip SOT marker seg
169     msg->phld = NULL;
170     msg->next = NULL;
171     
172     enqueue_message( msg, msgqueue);
173     cachemodel->th_model[ tile_id] = true;
174   }
175 }
176
177 void enqueue_tile( int tile_id, int level, msgqueue_param_t *msgqueue)
178 {
179   cachemodel_param_t *cachemodel;
180   target_param_t *target;
181   bool *tp_model;
182   Byte8_t numOftparts; // num of tile parts par tile
183   Byte8_t numOftiles;
184   index_param_t *codeidx;
185   faixbox_param_t *tilepart;
186   message_param_t *msg;
187   Byte8_t binOffset, binLength, class_id;
188   int i;
189
190   cachemodel = msgqueue->cachemodel;
191   target = cachemodel->target;
192   codeidx  = target->codeidx;
193   tilepart = codeidx->tilepart;
194   
195   numOftparts = get_nmax( tilepart);
196   numOftiles  = get_m( tilepart);
197
198   class_id = (numOftparts==1) ? TILE_MSG : EXT_TILE_MSG;
199   
200   if( tile_id < 0 || numOftiles <= tile_id){
201     fprintf( FCGI_stderr, "Error, Invalid tile-id %d\n", tile_id);
202     return;
203   }
204   
205   tp_model = &cachemodel->tp_model[ tile_id*numOftparts];
206
207   binOffset=0;
208   for( i=0; i<numOftparts-level; i++){
209     binLength = get_elemLen( tilepart, i, tile_id);
210     
211     if( !tp_model[i]){
212       msg = (message_param_t *)malloc( sizeof(message_param_t));
213       
214       msg->last_byte = (i==numOftparts-1);
215       msg->in_class_id = tile_id;
216       msg->class_id = class_id;
217       msg->csn = target->csn;
218       msg->bin_offset = binOffset;
219       msg->length = binLength;
220       msg->aux = numOftparts-i;
221       msg->res_offset = codeidx->offset+get_elemOff( tilepart, i, tile_id)/*-1*/;
222       msg->phld = NULL;
223       msg->next = NULL;
224
225       enqueue_message( msg, msgqueue);
226
227       tp_model[i] = true;
228     }
229     binOffset += binLength;
230   }
231 }
232
233 void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue)
234 {
235   cachemodel_param_t *cachemodel;
236   index_param_t *codeidx;
237   faixbox_param_t *precpacket;
238   message_param_t *msg;
239   Byte8_t nmax, binOffset, binLength;
240   int layer_id, numOflayers;
241   
242   cachemodel = msgqueue->cachemodel;
243   codeidx = cachemodel->target->codeidx;
244   precpacket = codeidx->precpacket[ comp_id];
245   numOflayers = codeidx->COD.numOflayers;
246
247   nmax = get_nmax(precpacket);
248   if( layers < 0)
249     layers = numOflayers;
250     
251   binOffset = 0;
252   for( layer_id = 0; layer_id < layers; layer_id++){
253
254     binLength = get_elemLen( precpacket, seq_id*numOflayers+layer_id, tile_id);
255     
256     if( !cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id*numOflayers+layer_id]){
257   
258       msg = (message_param_t *)malloc( sizeof(message_param_t));
259       msg->last_byte = (layer_id == (numOflayers-1));
260       msg->in_class_id = comp_precinct_id( tile_id, comp_id, seq_id, codeidx->SIZ.Csiz, codeidx->SIZ.XTnum * codeidx->SIZ.YTnum);
261       msg->class_id = PRECINCT_MSG;
262       msg->csn = cachemodel->target->csn;
263       msg->bin_offset = binOffset;
264       msg->length = binLength;
265       msg->aux = 0;
266       msg->res_offset = codeidx->offset+get_elemOff( precpacket, seq_id*numOflayers+layer_id, tile_id);
267       msg->phld = NULL;
268       msg->next = NULL;
269
270       enqueue_message( msg, msgqueue);
271       
272       cachemodel->pp_model[comp_id][ tile_id*nmax+seq_id*numOflayers+layer_id] = true;
273     }
274     binOffset += binLength;
275   }
276 }
277
278 Byte8_t comp_precinct_id( int t, int c, int s, int num_components, int num_tiles)
279 {
280   return t + (c + s * num_components ) * num_tiles;
281 }
282
283 void enqueue_box(  int meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
284 void enqueue_phld( int meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
285 void enqueue_boxcontents( int meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset);
286
287 void enqueue_metadata( int meta_id, msgqueue_param_t *msgqueue)
288 {
289   metadatalist_param_t *metadatalist;
290   metadata_param_t *metadata;
291   Byte8_t binOffset;
292
293   metadatalist = msgqueue->cachemodel->target->codeidx->metadatalist;
294   metadata = search_metadata( meta_id, metadatalist);
295   
296   if( !metadata){
297     fprintf( FCGI_stderr, "Error: metadata-bin %d not found\n", meta_id);
298     return;
299   }
300   binOffset = 0;
301   
302   if( metadata->boxlist)
303     enqueue_box( meta_id, metadata->boxlist, msgqueue, &binOffset);
304
305   if( metadata->placeholderlist)
306     enqueue_phld( meta_id, metadata->placeholderlist, msgqueue, &binOffset);
307
308   if( metadata->boxcontents)
309     enqueue_boxcontents( meta_id, metadata->boxcontents, msgqueue, &binOffset);
310   
311   msgqueue->last->last_byte = true;
312 }
313
314 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);
315
316 void enqueue_box( int meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
317 {
318   box_param_t *box;
319   message_param_t *msg;
320   
321   box = boxlist->first;
322   while( box){
323     msg = gene_metamsg( meta_id, *binOffset, box->length, box->offset, NULL, msgqueue->cachemodel->target->csn);
324     enqueue_message( msg, msgqueue);
325
326     *binOffset += box->length;
327     box = box->next;
328   }
329 }
330
331 void enqueue_phld( int meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
332 {
333   placeholder_param_t *phld;
334   message_param_t *msg;
335   
336   phld = phldlist->first;
337   while( phld){
338     msg = gene_metamsg( meta_id, *binOffset, phld->LBox, 0, phld, msgqueue->cachemodel->target->csn);
339     enqueue_message( msg, msgqueue);
340
341     *binOffset += phld->LBox;
342     phld = phld->next;
343   }
344 }
345
346 void enqueue_boxcontents( int meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
347 {
348   message_param_t *msg;
349
350   msg = gene_metamsg( meta_id, *binOffset, boxcontents->length, boxcontents->offset, NULL, msgqueue->cachemodel->target->csn);
351   enqueue_message( msg, msgqueue);
352   
353   *binOffset += boxcontents->length;
354 }
355
356 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)
357 {
358   message_param_t *msg;
359
360   msg = (message_param_t *)malloc( sizeof(message_param_t));
361     
362   msg->last_byte = false;
363   msg->in_class_id = meta_id;
364   msg->class_id = METADATA_MSG;
365   msg->csn = csn;
366   msg->bin_offset = binOffset;
367   msg->length = length;
368   msg->aux = 0; // non exist
369   msg->res_offset = res_offset;
370   msg->phld = phld;
371   msg->next = NULL;
372
373   return msg;
374 }
375
376 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue)
377 {
378   if( msgqueue->first)
379     msgqueue->last->next = msg;
380   else
381     msgqueue->first = msg;
382   
383   msgqueue->last = msg;
384 }
385
386
387 void emit_bin_id_vbas( Byte_t bb, Byte_t c, Byte8_t in_class_id);
388 void emit_vbas( Byte8_t code);
389 void emit_body( message_param_t *msg, int fd);
390 void emit_placeholder( placeholder_param_t *phld);
391
392 void emit_stream_from_msgqueue( msgqueue_param_t *msgqueue)
393 {
394   message_param_t *msg;
395   Byte8_t class_id, csn;
396   Byte_t bb, c;
397   
398   if( !(msgqueue))
399     return;
400
401   msg = msgqueue->first;
402   class_id = -1;
403   csn = -1;
404   while( msg){
405     if( msg->csn == csn){
406       if( msg->class_id == class_id)
407         bb = 1;
408       else{
409         bb = 2;
410         class_id = msg->class_id;
411       }
412     }
413     else{
414       bb = 3;
415       class_id = msg->class_id;
416       csn = msg->csn;
417     }
418
419     c = msg->last_byte ? 1 : 0;
420       
421     emit_bin_id_vbas( bb, c, msg->in_class_id);
422     
423     if( bb >= 2)
424       emit_vbas( class_id);
425     if (bb == 3)
426       emit_vbas( csn);
427     
428     emit_vbas( msg->bin_offset);
429     emit_vbas (msg->length);
430     
431     if( msg->class_id%2) // Aux is present only if the id is odd
432       emit_vbas( msg->aux);
433
434     if( msg->phld)
435       emit_placeholder( msg->phld);
436     else
437       emit_body( msg, msgqueue->cachemodel->target->fd);
438
439     msg = msg->next;
440   }
441 }
442
443 void emit_vbas_with_bytelen( Byte8_t code, int bytelength);
444 void print_binarycode( Byte8_t n, int segmentlen);
445
446 void emit_bin_id_vbas( Byte_t bb, Byte_t c, Byte8_t in_class_id)
447 {
448   int bytelength;
449   Byte8_t tmp;
450
451   // A.2.3 In-class identifiers 
452   // 7k-3bits, where k is the number of bytes in the VBAS
453   bytelength = 1;
454   tmp = in_class_id >> 4;
455   while( tmp){
456     bytelength ++;
457     tmp >>= 7;
458   }
459
460   in_class_id |= (((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7);
461   
462   emit_vbas_with_bytelen( in_class_id, bytelength);
463 }
464
465 void emit_vbas( Byte8_t code)
466 {
467   int bytelength;
468   Byte8_t tmp;
469
470   bytelength = 1;
471   tmp = code;
472   while( tmp >>= 7)
473     bytelength ++;
474
475   emit_vbas_with_bytelen( code, bytelength);
476 }
477
478 void emit_vbas_with_bytelen( Byte8_t code, int bytelength)
479 {
480   int n;
481   Byte8_t seg;
482   
483   n = bytelength - 1;
484   while( n >= 0) {
485     seg = ( code >> (n*7)) & 0x7f;
486     if( n)
487       seg |= 0x80;
488     fputc(( Byte4_t)seg, FCGI_stdout);
489     n--;
490   }
491 }
492
493 void emit_body( message_param_t *msg, int fd)
494 {
495   Byte_t *data;
496
497   if( lseek( fd, msg->res_offset, SEEK_SET)==-1){
498     fprintf( FCGI_stderr, "Error: fseek in emit_body()\n");
499     return;
500   }
501   
502   data = (Byte_t *)malloc( msg->length);
503   if( read( fd, data, msg->length) != msg->length){
504     free( data);
505     fprintf( FCGI_stderr, "Error: fread in emit_body()\n");
506     return;
507   }
508
509   if( fwrite( data, msg->length, 1, FCGI_stdout) < 1){
510     free( data);
511     fprintf( FCGI_stderr, "Error: fwrite in emit_body()\n");
512     return;
513   }
514   free(data);
515 }
516
517 void emit_bigendian_bytes( Byte8_t code, int bytelength);
518
519 void emit_placeholder( placeholder_param_t *phld)
520 {
521   emit_bigendian_bytes( phld->LBox, 4);
522   if( fwrite( phld->TBox, 4, 1, FCGI_stdout) < 1){
523     fprintf( FCGI_stderr, "Error: fwrite in emit_placeholder()\n");
524     return;
525   }
526   emit_bigendian_bytes( phld->Flags, 4);
527   emit_bigendian_bytes( phld->OrigID, 8);
528
529   if( fwrite( phld->OrigBH, phld->OrigBHlen, 1, FCGI_stdout) < 1){
530     fprintf( FCGI_stderr, "Error: fwrite in emit_placeholder()\n");
531     return;
532   }
533 }
534
535 void emit_bigendian_bytes( Byte8_t code, int bytelength)
536 {
537   int n;
538   Byte8_t seg;
539   
540   n = bytelength - 1;
541   while( n >= 0) {
542     seg = ( code >> (n*8)) & 0xff;
543     fputc(( Byte4_t)seg, FCGI_stdout);
544     n--;
545   }
546 }
547
548 void print_binarycode( Byte8_t n, int segmentlen)
549 {
550   char buf[256];
551   int i=0, j, k;
552
553   do{
554     buf[i++] = n%2 ? '1' : '0';
555   }while((n=n/2));
556
557   for( j=segmentlen-1; j>=i; j--)
558     putchar('0');
559   
560   for( j=i-1, k=0; j>=0; j--, k++){
561     putchar( buf[j]);
562     if( !((k+1)%segmentlen))
563       printf(" ");
564   }
565   printf("\n");
566 }
567
568 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id);
569 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem);
570
571 void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, Byte8_t offset, msgqueue_param_t *msgqueue)
572 {
573   Byte_t *ptr;  // stream pointer
574   message_param_t *msg;
575   Byte_t bb, c;
576   Byte8_t class_id, csn;
577
578   class_id = -1; // dummy
579   csn = -1;
580   ptr = JPIPstream;
581   while( ptr-JPIPstream < streamlen){
582     msg = (message_param_t *)malloc( sizeof(message_param_t));
583     
584     ptr = parse_bin_id_vbas( ptr, &bb, &c, &msg->in_class_id);
585     
586     msg->last_byte   = c == 1 ? true : false;
587     
588     if( bb >= 2)
589       ptr = parse_vbas( ptr, &class_id);
590
591     msg->class_id = class_id;
592     
593     if (bb == 3)
594       ptr = parse_vbas( ptr, &csn);
595     msg->csn = csn;
596     
597     ptr = parse_vbas( ptr, &msg->bin_offset);
598     ptr = parse_vbas( ptr, &msg->length);
599     
600     if( msg->class_id%2) // Aux is present only if the id is odd
601       ptr = parse_vbas( ptr, &msg->aux);
602     else
603       msg->aux = 0;
604     
605     msg->res_offset = ptr-JPIPstream+offset;   
606     msg->phld = NULL;
607     msg->next = NULL;
608
609     if(msgqueue->first)
610       msgqueue->last->next = msg;
611     else
612       msgqueue->first = msg;
613     msgqueue->last = msg;
614     
615     ptr += msg->length;
616   }
617 }
618
619 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *stream);
620
621 void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist)
622 {
623   message_param_t *msg;
624
625   if( metadatalist == NULL)
626     return;
627   
628   msg = msgqueue->first;
629   while( msg){
630     if( msg->class_id == METADATA_MSG){
631       metadata_param_t *metadata = gene_metadata( msg->in_class_id, NULL, NULL, NULL);
632       insert_metadata_into_list( metadata, metadatalist);
633       parse_metadata( metadata, msg, stream+msg->res_offset);
634     }
635     msg = msg->next;
636   }
637 }
638
639 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength);
640
641 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *datastream)
642 {
643   char *boxtype = (char *)(datastream+4);
644
645   msg->phld = NULL;
646
647   if( strncmp( boxtype, "phld", 4) == 0){
648     if( !metadata->placeholderlist)
649         metadata->placeholderlist = gene_placeholderlist();
650     
651     placeholder_param_t *phld = parse_phld( datastream, msg->length);
652     msg->phld = phld;
653     insert_placeholder_into_list( phld, metadata->placeholderlist);
654   }
655   else if( isalpha(boxtype[0]) && isalpha(boxtype[1]) &&
656            (isalnum(boxtype[2])||isblank(boxtype[2])) &&
657            (isalpha(boxtype[3])||isblank(boxtype[3]))){
658     if( !metadata->boxlist)
659       metadata->boxlist = gene_boxlist();
660     
661     box_param_t *box = gene_boxbyOffinStream( datastream, msg->res_offset);
662     insert_box_into_list( box, metadata->boxlist);
663   }
664   else
665     metadata->boxcontents = gene_boxcontents( msg->res_offset, msg->length);
666 }
667
668 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength)
669 {
670   placeholder_param_t *phld;
671
672   phld = (placeholder_param_t *)malloc( sizeof(placeholder_param_t));
673   
674   phld->LBox = big4( datastream);
675   strcpy( phld->TBox, "phld");
676   phld->Flags = big4( datastream+8);
677   phld->OrigID = big8( datastream+12);
678   phld->OrigBHlen = metalength - 20;
679   phld->OrigBH = (Byte_t *)malloc(phld->OrigBHlen);
680   memcpy( phld->OrigBH, datastream+20, phld->OrigBHlen);
681   phld->next = NULL;
682
683   return phld;
684 }
685
686 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id)
687 {
688   Byte_t code;
689   Byte_t *ptr;
690
691   ptr = streamptr;
692   code = *(ptr++);
693
694   *bb = (code >> 5) & 3;
695   *c  = (code >> 4) & 1;
696   
697   *in_class_id = code & 15;
698
699   while(code >> 7){
700     code = *(ptr++);
701     *in_class_id = (*in_class_id << 7) | (code & 0x7f);
702   }
703   return ptr;
704 }
705
706 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem)
707 {
708   Byte_t code;
709   Byte_t *ptr;
710   
711   *elem = 0;
712   ptr = streamptr;
713   do{
714     code = *(ptr++);
715     *elem = (*elem << 7) | (code & 0x7f);
716   }while(code >> 7);
717   
718   return ptr;
719 }
720
721 void delete_message_in_msgqueue( message_param_t **msg, msgqueue_param_t *msgqueue)
722 {
723   message_param_t *ptr;
724
725   if( !(*msg))
726     return;
727
728   if( *msg == msgqueue->first)
729     msgqueue->first = (*msg)->next;
730   else{
731     ptr = msgqueue->first;
732     while( ptr->next != *msg){
733       ptr=ptr->next;
734     }
735     
736     ptr->next = (*msg)->next;
737     
738     if( *msg == msgqueue->last)
739       msgqueue->last = ptr;
740   }
741   free( *msg);
742 }