4 * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
5 * Copyright (c) 2002-2014, Professor Benoit Macq
6 * Copyright (c) 2010-2011, Kaori Hagihara
7 * Copyright (c) 2011, Lucian Corlaciu, GSoC
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
34 #include <sys/types.h>
45 #include "msgqueue_manager.h"
46 #include "metadata_manager.h"
47 #include "index_manager.h"
48 #include "opj_inttypes.h"
51 #include "fcgi_stdio.h"
52 #define logstream FCGI_stdout
54 #define FCGI_stdout stdout
55 #define FCGI_stderr stderr
56 #define logstream stderr
59 msgqueue_param_t * gene_msgqueue( OPJ_BOOL stateless, cachemodel_param_t *cachemodel)
61 msgqueue_param_t *msgqueue;
63 msgqueue = (msgqueue_param_t *)opj_malloc( sizeof(msgqueue_param_t));
65 msgqueue->first = NULL;
66 msgqueue->last = NULL;
68 msgqueue->stateless = stateless;
69 msgqueue->cachemodel = cachemodel;
74 void delete_msgqueue( msgqueue_param_t **msgqueue)
76 message_param_t *ptr, *next;
81 ptr = (*msgqueue)->first;
88 if( (*msgqueue)->stateless && (*msgqueue)->cachemodel)
89 delete_cachemodel( &((*msgqueue)->cachemodel));
94 void print_msgqueue( msgqueue_param_t *msgqueue)
97 static const char *message_class[] = { "Precinct", "Ext-Prec", "TileHead", "non",
98 "Tile", "Ext-Tile", "Main", "non", "Meta"};
103 fprintf( logstream, "message queue:\n");
104 ptr = msgqueue->first;
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 );
113 fprintf( logstream, "\t aux: %" PRId64 "\n", ptr->aux );
114 fprintf( logstream, "\t last_byte: %d\n", ptr->last_byte );
116 print_placeholder( ptr->phld);
118 fprintf( logstream, "\t res_offset: %#" PRIx64 "\n", ptr->res_offset );
119 fprintf( logstream, "\n");
125 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue);
127 void enqueue_mainheader( msgqueue_param_t *msgqueue)
129 cachemodel_param_t *cachemodel;
130 target_param_t *target;
131 index_param_t *codeidx;
132 message_param_t *msg;
134 cachemodel = msgqueue->cachemodel;
135 target = cachemodel->target;
136 codeidx = target->codeidx;
138 msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
140 msg->last_byte = OPJ_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;
146 msg->length = codeidx->mhead_length;
147 msg->aux = 0; /* non exist*/
148 msg->res_offset = codeidx->offset;
152 enqueue_message( msg, msgqueue);
154 cachemodel->mhead_model = OPJ_TRUE;
157 void enqueue_tileheader( int tile_id, msgqueue_param_t *msgqueue)
159 cachemodel_param_t *cachemodel;
160 target_param_t *target;
161 index_param_t *codeidx;
162 message_param_t *msg;
164 cachemodel = msgqueue->cachemodel;
165 target = cachemodel->target;
166 codeidx = target->codeidx;
168 if( !cachemodel->th_model[ tile_id]){
169 msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
170 msg->last_byte = OPJ_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;
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*/
183 enqueue_message( msg, msgqueue);
184 cachemodel->th_model[ tile_id] = OPJ_TRUE;
188 void enqueue_tile( Byte4_t tile_id, int level, msgqueue_param_t *msgqueue)
190 cachemodel_param_t *cachemodel;
191 target_param_t *target;
193 Byte8_t numOftparts; /* num of tile parts par tile*/
195 index_param_t *codeidx;
196 faixbox_param_t *tilepart;
197 message_param_t *msg;
198 Byte8_t binOffset, binLength, class_id;
201 cachemodel = msgqueue->cachemodel;
202 target = cachemodel->target;
203 codeidx = target->codeidx;
204 tilepart = codeidx->tilepart;
206 numOftparts = get_nmax( tilepart);
207 numOftiles = get_m( tilepart);
209 class_id = (numOftparts==1) ? TILE_MSG : EXT_TILE_MSG;
211 if( /*tile_id < 0 ||*/ numOftiles <= (Byte8_t)tile_id){
212 fprintf( FCGI_stderr, "Error, Invalid tile-id %d\n", tile_id);
216 tp_model = &cachemodel->tp_model[ tile_id*numOftparts];
219 for( i=0; i<numOftparts-(Byte8_t)level; i++){
220 binLength = get_elemLen( tilepart, i, tile_id);
223 msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
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*/;
237 enqueue_message( msg, msgqueue);
239 tp_model[i] = OPJ_TRUE;
241 binOffset += binLength;
245 void enqueue_precinct( int seq_id, int tile_id, int comp_id, int layers, msgqueue_param_t *msgqueue)
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;
254 cachemodel = msgqueue->cachemodel;
255 codeidx = cachemodel->target->codeidx;
256 precpacket = codeidx->precpacket[ comp_id];
257 numOflayers = codeidx->COD.numOflayers;
259 nmax = get_nmax(precpacket);
260 assert( nmax < INT_MAX );
262 layers = numOflayers;
263 assert( tile_id >= 0 );
266 for( layer_id = 0; layer_id < layers; layer_id++){
268 binLength = get_elemLen( precpacket, (Byte8_t)(seq_id*numOflayers+layer_id), (Byte8_t)tile_id);
270 if( !cachemodel->pp_model[comp_id][tile_id*(int)nmax+seq_id*numOflayers+layer_id]){
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;
280 msg->res_offset = codeidx->offset+(OPJ_OFF_T)get_elemOff( precpacket, (Byte8_t)(seq_id*numOflayers+layer_id), (Byte8_t)tile_id);
284 enqueue_message( msg, msgqueue);
286 cachemodel->pp_model[comp_id][tile_id*(int)nmax+seq_id*numOflayers+layer_id] = OPJ_TRUE;
288 binOffset += binLength;
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)
295 return (Byte8_t)(t + (c + s * num_components ) * num_tiles);
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);
302 void enqueue_metadata( Byte8_t meta_id, msgqueue_param_t *msgqueue)
304 metadatalist_param_t *metadatalist;
305 metadata_param_t *metadata;
308 metadatalist = msgqueue->cachemodel->target->codeidx->metadatalist;
309 metadata = search_metadata( meta_id, metadatalist);
312 fprintf( FCGI_stderr, "Error: metadata-bin %" PRIu64 " not found\n", meta_id);
317 if( metadata->boxlist)
318 enqueue_box( meta_id, metadata->boxlist, msgqueue, &binOffset);
320 if( metadata->placeholderlist)
321 enqueue_phld( meta_id, metadata->placeholderlist, msgqueue, &binOffset);
323 if( metadata->boxcontents)
324 enqueue_boxcontents( meta_id, metadata->boxcontents, msgqueue, &binOffset);
326 msgqueue->last->last_byte = OPJ_TRUE;
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);
331 void enqueue_box( Byte8_t meta_id, boxlist_param_t *boxlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
334 message_param_t *msg;
336 box = boxlist->first;
337 assert( msgqueue->cachemodel->target->csn >= 0);
339 msg = gene_metamsg( meta_id, *binOffset, box->length, box->offset, NULL, (Byte8_t)msgqueue->cachemodel->target->csn);
340 enqueue_message( msg, msgqueue);
342 *binOffset += box->length;
347 void enqueue_phld( Byte8_t meta_id, placeholderlist_param_t *phldlist, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
349 placeholder_param_t *phld;
350 message_param_t *msg;
352 phld = phldlist->first;
353 assert( msgqueue->cachemodel->target->csn >= 0);
355 msg = gene_metamsg( meta_id, *binOffset, phld->LBox, 0, phld, (Byte8_t)msgqueue->cachemodel->target->csn);
356 enqueue_message( msg, msgqueue);
358 *binOffset += phld->LBox;
363 void enqueue_boxcontents( Byte8_t meta_id, boxcontents_param_t *boxcontents, msgqueue_param_t *msgqueue, Byte8_t *binOffset)
365 message_param_t *msg;
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);
372 *binOffset += boxcontents->length;
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)
377 message_param_t *msg;
379 msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
381 msg->last_byte = OPJ_FALSE;
382 msg->in_class_id = meta_id;
383 msg->class_id = METADATA_MSG;
385 msg->bin_offset = binOffset;
386 msg->length = length;
387 msg->aux = 0; /* non exist*/
388 msg->res_offset = res_offset;
395 void enqueue_message( message_param_t *msg, msgqueue_param_t *msgqueue)
398 msgqueue->last->next = msg;
400 msgqueue->first = msg;
402 msgqueue->last = msg;
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);
410 void recons_stream_from_msgqueue( msgqueue_param_t *msgqueue, int tmpfd)
412 message_param_t *msg;
413 Byte8_t class_id, csn;
419 msg = msgqueue->first;
420 class_id = (Byte8_t)-1;
423 if( msg->csn == csn){
424 if( msg->class_id == class_id)
428 class_id = msg->class_id;
433 class_id = msg->class_id;
437 c = msg->last_byte ? 1 : 0;
439 add_bin_id_vbas_stream( bb, c, msg->in_class_id, tmpfd);
442 add_vbas_stream( class_id, tmpfd);
444 add_vbas_stream( csn, tmpfd);
446 add_vbas_stream( msg->bin_offset, tmpfd);
447 add_vbas_stream (msg->length, tmpfd);
449 if( msg->class_id%2) /* Aux is present only if the id is odd*/
450 add_vbas_stream( msg->aux, tmpfd);
453 add_placeholder_stream( msg->phld, tmpfd);
455 add_body_stream( msg, msgqueue->cachemodel->target->fd, tmpfd);
461 void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd);
462 void print_binarycode( Byte8_t n, int segmentlen);
464 void add_bin_id_vbas_stream( Byte_t bb, Byte_t c, Byte8_t in_class_id, int tmpfd)
469 /* A.2.3 In-class identifiers */
470 /* 7k-3bits, where k is the number of bytes in the VBAS*/
472 tmp = in_class_id >> 4;
478 in_class_id |= (Byte8_t)((((bb & 3) << 5) | (c & 1) << 4) << ((bytelength-1)*7));
480 add_vbas_with_bytelen_stream( in_class_id, bytelength, tmpfd);
483 void add_vbas_stream( Byte8_t code, int tmpfd)
493 add_vbas_with_bytelen_stream( code, bytelength, tmpfd);
496 void add_vbas_with_bytelen_stream( Byte8_t code, int bytelength, int tmpfd)
503 seg = ( code >> (n*7)) & 0x7f;
506 if( write( tmpfd, ( Byte4_t *)&seg, 1) != 1){
507 fprintf( FCGI_stderr, "Error: failed to write vbas\n");
514 void add_body_stream( message_param_t *msg, int fd, int tmpfd)
518 if( !(data = fetch_bytes( fd, msg->res_offset, msg->length))){
519 fprintf( FCGI_stderr, "Error: fetch_bytes in add_body_stream()\n");
523 if( write( tmpfd, data, msg->length) < 1){
525 fprintf( FCGI_stderr, "Error: fwrite in add_body_stream()\n");
531 void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd);
533 void add_placeholder_stream( placeholder_param_t *phld, int tmpfd)
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");
540 add_bigendian_bytestream( phld->Flags, 4, tmpfd);
541 add_bigendian_bytestream( phld->OrigID, 8, tmpfd);
543 if( write( tmpfd, phld->OrigBH, phld->OrigBHlen) < 1){
544 fprintf( FCGI_stderr, "Error: fwrite in add_placeholder_stream()\n");
549 void add_bigendian_bytestream( Byte8_t code, int bytelength, int tmpfd)
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");
565 void print_binarycode( Byte8_t n, int segmentlen)
571 buf[i++] = n%2 ? '1' : '0';
574 for( j=segmentlen-1; j>=i; j--)
577 for( j=i-1, k=0; j>=0; j--, k++){
579 if( !((k+1)%segmentlen))
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);
588 void parse_JPIPstream( Byte_t *JPIPstream, Byte8_t streamlen, OPJ_OFF_T offset, msgqueue_param_t *msgqueue)
590 Byte_t *ptr; /* stream pointer*/
591 message_param_t *msg;
593 Byte8_t class_id, csn;
595 class_id = (Byte8_t)-1; /* dummy*/
598 while( (Byte8_t)(ptr-JPIPstream) < streamlen){
599 msg = (message_param_t *)opj_malloc( sizeof(message_param_t));
601 ptr = parse_bin_id_vbas( ptr, &bb, &c, &msg->in_class_id);
603 msg->last_byte = c == 1 ? OPJ_TRUE : OPJ_FALSE;
606 ptr = parse_vbas( ptr, &class_id);
608 msg->class_id = class_id;
611 ptr = parse_vbas( ptr, &csn);
614 ptr = parse_vbas( ptr, &msg->bin_offset);
615 ptr = parse_vbas( ptr, &msg->length);
617 if( msg->class_id%2) /* Aux is present only if the id is odd*/
618 ptr = parse_vbas( ptr, &msg->aux);
622 msg->res_offset = ptr-JPIPstream+offset;
627 msgqueue->last->next = msg;
629 msgqueue->first = msg;
630 msgqueue->last = msg;
636 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *stream);
638 void parse_metamsg( msgqueue_param_t *msgqueue, Byte_t *stream, Byte8_t streamlen, metadatalist_param_t *metadatalist)
640 message_param_t *msg;
643 if( metadatalist == NULL)
646 msg = msgqueue->first;
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);
657 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength);
659 void parse_metadata( metadata_param_t *metadata, message_param_t *msg, Byte_t *datastream)
662 placeholder_param_t *phld;
663 char *boxtype = (char *)(datastream+4);
667 if( strncmp( boxtype, "phld", 4) == 0){
668 if( !metadata->placeholderlist)
669 metadata->placeholderlist = gene_placeholderlist();
671 phld = parse_phld( datastream, msg->length);
673 insert_placeholder_into_list( phld, metadata->placeholderlist);
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();
681 box = gene_boxbyOffinStream( datastream, msg->res_offset);
682 insert_box_into_list( box, metadata->boxlist);
685 metadata->boxcontents = gene_boxcontents( msg->res_offset, msg->length);
688 placeholder_param_t * parse_phld( Byte_t *datastream, Byte8_t metalength)
690 placeholder_param_t *phld;
692 phld = (placeholder_param_t *)opj_malloc( sizeof(placeholder_param_t));
694 phld->LBox = big4( datastream);
695 strncpy( phld->TBox, "phld", 4);
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);
706 Byte_t * parse_bin_id_vbas( Byte_t *streamptr, Byte_t *bb, Byte_t *c, Byte8_t *in_class_id)
714 *bb = (code >> 5) & 3;
715 *c = (code >> 4) & 1;
717 *in_class_id = code & 15;
721 *in_class_id = (*in_class_id << 7) | (code & 0x7f);
726 Byte_t * parse_vbas( Byte_t *streamptr, Byte8_t *elem)
735 *elem = (*elem << 7) | (code & 0x7f);
741 void delete_message_in_msgqueue( message_param_t **msg, msgqueue_param_t *msgqueue)
743 message_param_t *ptr;
748 if( *msg == msgqueue->first)
749 msgqueue->first = (*msg)->next;
751 ptr = msgqueue->first;
752 while( ptr->next != *msg){
756 ptr->next = (*msg)->next;
758 if( *msg == msgqueue->last)
759 msgqueue->last = ptr;