manage case 0 frames inside yuv_num_frames function and correct some warnings with...
[openjpeg.git] / libopenjpeg / jpwl / jpwl.c
1 /*\r
2  * Copyright (c) 2001-2003, David Janssens\r
3  * Copyright (c) 2002-2003, Yannick Verschueren\r
4  * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe\r
5  * Copyright (c) 2005, Herve Drolon, FreeImage Team\r
6  * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium\r
7  * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy\r
8  * All rights reserved.\r
9  *\r
10  * Redistribution and use in source and binary forms, with or without\r
11  * modification, are permitted provided that the following conditions\r
12  * are met:\r
13  * 1. Redistributions of source code must retain the above copyright\r
14  *    notice, this list of conditions and the following disclaimer.\r
15  * 2. Redistributions in binary form must reproduce the above copyright\r
16  *    notice, this list of conditions and the following disclaimer in the\r
17  *    documentation and/or other materials provided with the distribution.\r
18  *\r
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
29  * POSSIBILITY OF SUCH DAMAGE.\r
30  */\r
31 \r
32 #include "opj_includes.h"\r
33 \r
34 #ifdef USE_JPWL\r
35 \r
36 /** @defgroup JPWL JPWL - JPEG-2000 Part11 (JPWL) codestream manager */\r
37 /*@{*/\r
38 \r
39 /** @name Local static variables */\r
40 /*@{*/\r
41 \r
42 /** number of JPWL prepared markers */\r
43 static int jwmarker_num;\r
44 /** properties of JPWL markers to insert */\r
45 static jpwl_marker_t jwmarker[JPWL_MAX_NO_MARKERS]; \r
46 \r
47 /*@}*/\r
48 \r
49 /*@}*/\r
50 \r
51 /** @name Local static functions */\r
52 /*@{*/\r
53 \r
54 /** create an EPC marker segment\r
55 @param j2k J2K compressor handle\r
56 @param esd_on true if ESD is activated\r
57 @param red_on true if RED is activated\r
58 @param epb_on true if EPB is activated\r
59 @param info_on true if informative techniques are activated\r
60 @return returns the freshly created EPC\r
61 */\r
62 jpwl_epc_ms_t *jpwl_epc_create(opj_j2k_t *j2k, opj_bool esd_on, opj_bool red_on, opj_bool epb_on, opj_bool info_on);\r
63 \r
64 /*@}*/\r
65 \r
66 /** create an EPC marker segment\r
67 @param j2k J2K compressor handle\r
68 @param comps considered component (-1=average, 0/1/2/...=component no.)\r
69 @param addrm addressing mode (0=packet, 1=byte range, 2=packet range, 3=reserved)\r
70 @param ad_size size of addresses (2/4 bytes)\r
71 @param senst sensitivity type\r
72 @param se_size sensitivity values size (1/2 bytes)\r
73 @param tileno tile where this ESD lies (-1 means MH)\r
74 @param svalnum number of sensitivity values (if 0, they will be automatically filled)\r
75 @param sensval pointer to an array of sensitivity values (if NULL, they will be automatically filled)\r
76 @return returns the freshly created ESD\r
77 */\r
78 jpwl_esd_ms_t *jpwl_esd_create(opj_j2k_t *j2k, int comps, \r
79         unsigned char addrm, unsigned char ad_size,\r
80         unsigned char senst, int se_size, int tileno,\r
81         unsigned long int svalnum, void *sensval);\r
82                         \r
83 /** this function is used to compare two JPWL markers based on\r
84 their relevant wishlist position\r
85 @param arg1 pointer to first marker\r
86 @param arg2 pointer to second marker\r
87 @return 1 if arg1>arg2, 0 if arg1=arg2, -1 if arg1<arg2\r
88 */\r
89 int jpwl_markcomp(const void *arg1, const void *arg2);\r
90 \r
91 /** write an EPB MS to a buffer\r
92 @param j2k J2K compressor handle\r
93 @param epbmark pointer to the EPB MS\r
94 @param buf pointer to the memory buffer\r
95 */\r
96 void jpwl_epb_write(opj_j2k_t *j2k, jpwl_epb_ms_t *epbmark, unsigned char *buf);\r
97 \r
98 /** write an EPC MS to a buffer\r
99 @param j2k J2K compressor handle\r
100 @param epcmark pointer to the EPC MS\r
101 @param buf pointer to the memory buffer\r
102 */\r
103 void jpwl_epc_write(opj_j2k_t *j2k, jpwl_epc_ms_t *epcmark, unsigned char *buf);\r
104 \r
105 /** write an ESD MS to a buffer\r
106 @param j2k J2K compressor handle\r
107 @param esdmark pointer to the ESD MS\r
108 @param buf pointer to the memory buffer\r
109 */\r
110 void jpwl_esd_write(opj_j2k_t *j2k, jpwl_esd_ms_t *esdmark, unsigned char *buf);\r
111 \r
112 /*-----------------------------------------------------------------*/\r
113 \r
114 void jpwl_encode(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {\r
115 \r
116         int mm;\r
117 \r
118         /* let's reset some settings */\r
119 \r
120         /* clear the existing markers */\r
121         for (mm = 0; mm < jwmarker_num; mm++) {\r
122 \r
123                 switch (jwmarker[mm].id) {\r
124 \r
125                 case J2K_MS_EPB:\r
126                         opj_free(jwmarker[mm].m.epbmark);\r
127                         break;\r
128 \r
129                 case J2K_MS_EPC:\r
130                         opj_free(jwmarker[mm].m.epcmark);\r
131                         break;\r
132 \r
133                 case J2K_MS_ESD:\r
134                         opj_free(jwmarker[mm].m.esdmark);\r
135                         break;\r
136 \r
137                 case J2K_MS_RED:\r
138                         opj_free(jwmarker[mm].m.redmark);\r
139                         break;\r
140 \r
141                 default:\r
142                         break;\r
143                 }\r
144         }\r
145 \r
146         /* clear the marker structure array */\r
147         memset(jwmarker, 0, sizeof(jpwl_marker_t) * JPWL_MAX_NO_MARKERS);\r
148 \r
149         /* no more markers in the list */\r
150         jwmarker_num = 0;\r
151 \r
152         /* let's begin creating a marker list, according to user wishes */\r
153         jpwl_prepare_marks(j2k, cio, image);\r
154 \r
155         /* now we dump the JPWL markers on the codestream */\r
156         jpwl_dump_marks(j2k, cio, image);\r
157 \r
158         /* do not know exactly what is this for,\r
159         but it gets called during index creation */\r
160         j2k->pos_correction = 0;\r
161 \r
162 }\r
163 \r
164 void j2k_add_marker(opj_codestream_info_t *cstr_info, unsigned short int type, int pos, int len) {\r
165 \r
166         if (!cstr_info)\r
167                 return;\r
168 \r
169         /* expand the list? */\r
170         if ((cstr_info->marknum + 1) > cstr_info->maxmarknum) {\r
171                 cstr_info->maxmarknum = 100 + (int) ((float) cstr_info->maxmarknum * 1.0F);\r
172                 cstr_info->marker = (opj_marker_info_t*)opj_realloc(cstr_info->marker, cstr_info->maxmarknum);\r
173         }\r
174 \r
175         /* add the marker */\r
176         cstr_info->marker[cstr_info->marknum].type = type;\r
177         cstr_info->marker[cstr_info->marknum].pos = pos;\r
178         cstr_info->marker[cstr_info->marknum].len = len;\r
179         cstr_info->marknum++;\r
180 \r
181 }\r
182 \r
183 void jpwl_prepare_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {\r
184 \r
185         unsigned short int socsiz_len = 0;\r
186         int ciopos = cio_tell(cio), soc_pos = j2k->cstr_info->main_head_start;\r
187         unsigned char *socp = NULL;\r
188 \r
189         int tileno, acc_tpno, tpno, tilespec, hprot, sens, pprot, packspec, lastileno, packno;\r
190 \r
191         jpwl_epb_ms_t *epb_mark;\r
192         jpwl_epc_ms_t *epc_mark;\r
193         jpwl_esd_ms_t *esd_mark;\r
194 \r
195         /* find (SOC + SIZ) length */\r
196         /* I assume SIZ is always the first marker after SOC */\r
197         cio_seek(cio, soc_pos + 4);\r
198         socsiz_len = (unsigned short int) cio_read(cio, 2) + 4; /* add the 2 marks length itself */\r
199         cio_seek(cio, soc_pos + 0);\r
200         socp = cio_getbp(cio); /* pointer to SOC */\r
201 \r
202         /* \r
203          EPC MS for Main Header: if we are here it's required\r
204         */\r
205         /* create the EPC */\r
206         if ((epc_mark = jpwl_epc_create(\r
207                         j2k,\r
208                         j2k->cp->esd_on, /* is ESD present? */\r
209                         j2k->cp->red_on, /* is RED present? */\r
210                         j2k->cp->epb_on, /* is EPB present? */\r
211                         OPJ_FALSE /* are informative techniques present? */\r
212                 ))) {\r
213 \r
214                 /* Add this marker to the 'insertanda' list */\r
215                 if (epc_mark) {\r
216                         jwmarker[jwmarker_num].id = J2K_MS_EPC; /* its type */\r
217                         jwmarker[jwmarker_num].m.epcmark = epc_mark; /* the EPC */\r
218                         jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */\r
219                         jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.1; /* not so first */\r
220                         jwmarker[jwmarker_num].len = epc_mark->Lepc; /* its length */\r
221                         jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */\r
222                         jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
223                         jwmarker[jwmarker_num].parms_ready = OPJ_FALSE; /* not ready */\r
224                         jwmarker[jwmarker_num].data_ready = OPJ_TRUE; /* ready */\r
225                         jwmarker_num++;\r
226                 };\r
227 \r
228                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
229                         "MH  EPC : setting %s%s%s\n",\r
230                         j2k->cp->esd_on ? "ESD, " : "",\r
231                         j2k->cp->red_on ? "RED, " : "",\r
232                         j2k->cp->epb_on ? "EPB, " : ""\r
233                         );\r
234 \r
235         } else {\r
236                 /* ooops, problems */\r
237                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPC\n");                              \r
238         };\r
239 \r
240         /* \r
241          ESD MS for Main Header\r
242         */\r
243         /* first of all, must MH have an ESD MS? */\r
244         if (j2k->cp->esd_on && (j2k->cp->sens_MH >= 0)) {\r
245 \r
246                 /* Create the ESD */\r
247                 if ((esd_mark = jpwl_esd_create(\r
248                         j2k, /* this encoder handle */\r
249                         -1, /* we are averaging over all components */\r
250                         (unsigned char) j2k->cp->sens_range, /* range method */\r
251                         (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing */\r
252                         (unsigned char) j2k->cp->sens_MH, /* sensitivity method */\r
253                         j2k->cp->sens_size, /* sensitivity size */\r
254                         -1, /* this ESD is in main header */\r
255                         0 /*j2k->cstr_info->num*/, /* number of packets in codestream */\r
256                         NULL /*sensval*/ /* pointer to sensitivity data of packets */\r
257                         ))) {\r
258                         \r
259                         /* Add this marker to the 'insertanda' list */\r
260                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
261                                 jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */\r
262                                 jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */\r
263                                 jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* we choose to place it after SIZ */\r
264                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */\r
265                                 jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */\r
266                                 jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* not ready, yet */\r
267                                 jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
268                                 jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */\r
269                                 jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */\r
270                                 jwmarker_num++;\r
271                         }\r
272 \r
273                         opj_event_msg(j2k->cinfo, EVT_INFO,\r
274                                 "MH  ESDs: method %d\n",\r
275                                 j2k->cp->sens_MH\r
276                                 );\r
277 \r
278                 } else {\r
279                         /* ooops, problems */\r
280                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH ESD\n");                              \r
281                 };\r
282 \r
283         }\r
284 \r
285         /* \r
286          ESD MSs for Tile Part Headers \r
287         */\r
288         /* cycle through tiles */\r
289         sens = -1; /* default spec: no ESD */\r
290         tilespec = 0; /* first tile spec */\r
291         acc_tpno = 0;\r
292         for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {\r
293 \r
294                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
295                         "Tile %d has %d tile part(s)\n",\r
296                         tileno, j2k->cstr_info->tile[tileno].num_tps\r
297                         );\r
298 \r
299                 /* for every tile part in the tile */\r
300                 for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) {\r
301         \r
302                         int sot_len, Psot, Psotp, mm;\r
303                         unsigned long sot_pos, post_sod_pos;\r
304 \r
305                         unsigned long int left_THmarks_len;\r
306 \r
307                         /******* sot_pos = j2k->cstr_info->tile[tileno].start_pos; */\r
308                         sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;\r
309                         cio_seek(cio, sot_pos + 2); \r
310                         sot_len = cio_read(cio, 2); /* SOT Len */\r
311                         cio_skip(cio, 2);\r
312                         Psotp = cio_tell(cio);\r
313                         Psot = cio_read(cio, 4); /* tile length */\r
314 \r
315                         /******* post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */\r
316                         post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;\r
317                         left_THmarks_len = post_sod_pos - sot_pos;\r
318 \r
319                         /* add all the lengths of the markers which are len-ready and stay within SOT and SOD */\r
320                         for (mm = 0; mm < jwmarker_num; mm++) {\r
321                                 if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {\r
322                                         if (jwmarker[mm].len_ready)\r
323                                                 left_THmarks_len += jwmarker[mm].len + 2;\r
324                                         else {\r
325                                                 opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",\r
326                                                         jwmarker[mm].id, jwmarker[mm].dpos);                            \r
327                                                 exit(1);\r
328                                         }\r
329                                 }\r
330                         }\r
331 \r
332                         /******* if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == tileno)) */\r
333                         if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->sens_TPH_tileno[tilespec] == acc_tpno))\r
334                                 /* we got a specification from this tile onwards */\r
335                                 sens = j2k->cp->sens_TPH[tilespec++];\r
336                 \r
337                         /* must this TPH have an ESD MS? */\r
338                         if (j2k->cp->esd_on && (sens >= 0)) {\r
339 \r
340                                 /* Create the ESD */\r
341                                 if ((esd_mark = jpwl_esd_create(\r
342                                         j2k, /* this encoder handle */\r
343                                         -1, /* we are averaging over all components */\r
344                                         (unsigned char) j2k->cp->sens_range, /* range method */\r
345                                         (unsigned char) j2k->cp->sens_addr, /* sensitivity addressing size */\r
346                                         (unsigned char) sens, /* sensitivity method */\r
347                                         j2k->cp->sens_size, /* sensitivity value size */\r
348                                         tileno, /* this ESD is in a tile */\r
349                                         0, /* number of packets in codestream */\r
350                                         NULL /* pointer to sensitivity data of packets */\r
351                                         ))) {\r
352                                         \r
353                                         /* Add this marker to the 'insertanda' list */\r
354                                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
355                                                 jwmarker[jwmarker_num].id = J2K_MS_ESD; /* its type */\r
356                                                 jwmarker[jwmarker_num].m.esdmark = esd_mark; /* the EPB */\r
357                                                 /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */\r
358                                                 jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */\r
359                                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos + 0.2; /* not first at all! */\r
360                                                 jwmarker[jwmarker_num].len = esd_mark->Lesd; /* its length */\r
361                                                 jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready, yet */\r
362                                                 jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
363                                                 jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* not ready */\r
364                                                 jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* ready */\r
365                                                 jwmarker_num++;\r
366                                         }\r
367 \r
368                                         /* update Psot of the tile  */\r
369                                         cio_seek(cio, Psotp);\r
370                                         cio_write(cio, Psot + esd_mark->Lesd + 2, 4);\r
371 \r
372                                         opj_event_msg(j2k->cinfo, EVT_INFO,\r
373                                                 /******* "TPH ESDs: tile %02d, method %d\n", */\r
374                                                 "TPH ESDs: tile %02d, part %02d, method %d\n",\r
375                                                 /******* tileno, */\r
376                                                 tileno, tpno,\r
377                                                 sens\r
378                                                 );\r
379 \r
380                                 } else {\r
381                                         /* ooops, problems */\r
382                                         /***** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d\n", tileno); */\r
383                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH ESD #%d,%d\n", tileno, tpno);\r
384                                 };\r
385 \r
386                         }\r
387                         \r
388                 }\r
389         \r
390         };\r
391 \r
392         /* \r
393          EPB MS for Main Header\r
394         */\r
395         /* first of all, must MH have an EPB MS? */\r
396         if (j2k->cp->epb_on && (j2k->cp->hprot_MH > 0)) {\r
397 \r
398                 int mm;\r
399 \r
400                 /* position of SOT */\r
401                 unsigned int sot_pos = j2k->cstr_info->main_head_end + 1;\r
402 \r
403                 /* how much space is there between end of SIZ and beginning of SOT? */\r
404                 int left_MHmarks_len = sot_pos - socsiz_len;\r
405 \r
406                 /* add all the lengths of the markers which are len-ready and stay within SOC and SOT */\r
407                 for (mm = 0; mm < jwmarker_num; mm++) {\r
408                         if ((jwmarker[mm].pos >=0) && (jwmarker[mm].pos < sot_pos)) {\r
409                                 if (jwmarker[mm].len_ready)\r
410                                         left_MHmarks_len += jwmarker[mm].len + 2;\r
411                                 else {\r
412                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up MH EPB\n",\r
413                                                 jwmarker[mm].id, jwmarker[mm].dpos);                            \r
414                                         exit(1);\r
415                                 }\r
416                         }\r
417                 }\r
418 \r
419                 /* Create the EPB */\r
420                 if ((epb_mark = jpwl_epb_create(\r
421                         j2k, /* this encoder handle */\r
422                         OPJ_TRUE, /* is it the latest? */\r
423                         OPJ_TRUE, /* is it packed? not for now */\r
424                         -1, /* we are in main header */\r
425                         0, /* its index is 0 (first) */\r
426                         j2k->cp->hprot_MH, /* protection type parameters of data */\r
427                         socsiz_len, /* pre-data: only SOC+SIZ */\r
428                         left_MHmarks_len /* post-data: from SOC to SOT, and all JPWL markers within */\r
429                         ))) {\r
430                         \r
431                         /* Add this marker to the 'insertanda' list */\r
432                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
433                                 jwmarker[jwmarker_num].id = J2K_MS_EPB; /* its type */\r
434                                 jwmarker[jwmarker_num].m.epbmark = epb_mark; /* the EPB */\r
435                                 jwmarker[jwmarker_num].pos = soc_pos + socsiz_len; /* after SIZ */\r
436                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */\r
437                                 jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */\r
438                                 jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */\r
439                                 jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
440                                 jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */\r
441                                 jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */\r
442                                 jwmarker_num++;\r
443                         }\r
444 \r
445                         opj_event_msg(j2k->cinfo, EVT_INFO,\r
446                                 "MH  EPB : prot. %d\n",\r
447                                 j2k->cp->hprot_MH\r
448                                 );\r
449 \r
450                 } else {\r
451                         /* ooops, problems */\r
452                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create MH EPB\n");                              \r
453                 };\r
454         }\r
455 \r
456         /* \r
457          EPB MSs for Tile Parts\r
458         */\r
459         /* cycle through TPHs */\r
460         hprot = j2k->cp->hprot_MH; /* default spec */\r
461         tilespec = 0; /* first tile spec */\r
462         lastileno = 0;\r
463         packspec = 0;\r
464         pprot = -1;\r
465         acc_tpno = 0;\r
466         for (tileno = 0; tileno < j2k->cstr_info->tw * j2k->cstr_info->th; tileno++) {\r
467 \r
468                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
469                         "Tile %d has %d tile part(s)\n",\r
470                         tileno, j2k->cstr_info->tile[tileno].num_tps\r
471                         );\r
472 \r
473                 /* for every tile part in the tile */\r
474                 for (tpno = 0; tpno < j2k->cstr_info->tile[tileno].num_tps; tpno++, acc_tpno++) { \r
475                 \r
476                         int sot_len, Psot, Psotp, mm, epb_index = 0, prot_len = 0;\r
477                         unsigned long sot_pos, post_sod_pos;\r
478                         unsigned long int left_THmarks_len/*, epbs_len = 0*/;\r
479                         int startpack = 0, stoppack = j2k->cstr_info->packno;\r
480                         int first_tp_pack, last_tp_pack;\r
481                         jpwl_epb_ms_t *tph_epb = NULL;\r
482 \r
483                         /****** sot_pos = j2k->cstr_info->tile[tileno].start_pos; */\r
484                         sot_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos;\r
485                         cio_seek(cio, sot_pos + 2); \r
486                         sot_len = cio_read(cio, 2); /* SOT Len */\r
487                         cio_skip(cio, 2);\r
488                         Psotp = cio_tell(cio);\r
489                         Psot = cio_read(cio, 4); /* tile length */\r
490 \r
491                         /* a-priori length of the data dwelling between SOT and SOD */\r
492                         /****** post_sod_pos = j2k->cstr_info->tile[tileno].end_header + 1; */\r
493                         post_sod_pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_end_header + 1;\r
494                         left_THmarks_len = post_sod_pos - (sot_pos + sot_len + 2);\r
495 \r
496                         /* add all the lengths of the JPWL markers which are len-ready and stay within SOT and SOD */\r
497                         for (mm = 0; mm < jwmarker_num; mm++) {\r
498                                 if ((jwmarker[mm].pos >= sot_pos) && (jwmarker[mm].pos < post_sod_pos)) {\r
499                                         if (jwmarker[mm].len_ready)\r
500                                                 left_THmarks_len += jwmarker[mm].len + 2;\r
501                                         else {\r
502                                                 opj_event_msg(j2k->cinfo, EVT_ERROR, "MS %x in %f is not len-ready: could not set up TH EPB\n",\r
503                                                         jwmarker[mm].id, jwmarker[mm].dpos);                            \r
504                                                 exit(1);\r
505                                         }\r
506                                 }\r
507                         }\r
508 \r
509                         /****** if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == tileno)) */\r
510                         if ((tilespec < JPWL_MAX_NO_TILESPECS) && (j2k->cp->hprot_TPH_tileno[tilespec] == acc_tpno))\r
511                                 /* we got a specification from this tile part onwards */\r
512                                 hprot = j2k->cp->hprot_TPH[tilespec++];\r
513                 \r
514                         /* must this TPH have an EPB MS? */\r
515                         if (j2k->cp->epb_on && (hprot > 0)) {\r
516 \r
517                                 /* Create the EPB */\r
518                                 if ((epb_mark = jpwl_epb_create(\r
519                                         j2k, /* this encoder handle */\r
520                                         OPJ_FALSE, /* is it the latest? in TPH, no for now (if huge data size in TPH, we'd need more) */\r
521                                         OPJ_TRUE, /* is it packed? yes for now */\r
522                                         tileno, /* we are in TPH */\r
523                                         epb_index++, /* its index is 0 (first) */\r
524                                         hprot, /* protection type parameters of following data */\r
525                                         sot_len + 2, /* pre-data length: only SOT */\r
526                                         left_THmarks_len /* post-data length: from SOT end to SOD inclusive */\r
527                                         ))) {\r
528                                         \r
529                                         /* Add this marker to the 'insertanda' list */\r
530                                         if (jwmarker_num < JPWL_MAX_NO_MARKERS) {\r
531                                                 jwmarker[jwmarker_num].id = J2K_MS_EPB; /* its type */\r
532                                                 jwmarker[jwmarker_num].m.epbmark = epb_mark; /* the EPB */\r
533                                                 /****** jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].start_pos + sot_len + 2; */ /* after SOT */\r
534                                                 jwmarker[jwmarker_num].pos = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2; /* after SOT */\r
535                                                 jwmarker[jwmarker_num].dpos = (double) jwmarker[jwmarker_num].pos; /* first first first! */\r
536                                                 jwmarker[jwmarker_num].len = epb_mark->Lepb; /* its length */\r
537                                                 jwmarker[jwmarker_num].len_ready = OPJ_TRUE; /* ready */\r
538                                                 jwmarker[jwmarker_num].pos_ready = OPJ_TRUE; /* ready */\r
539                                                 jwmarker[jwmarker_num].parms_ready = OPJ_TRUE; /* ready */\r
540                                                 jwmarker[jwmarker_num].data_ready = OPJ_FALSE; /* not ready */\r
541                                                 jwmarker_num++;\r
542                                         }\r
543 \r
544                                         /* update Psot of the tile  */\r
545                                         Psot += epb_mark->Lepb + 2;\r
546 \r
547                                         opj_event_msg(j2k->cinfo, EVT_INFO,\r
548                                                 /***** "TPH EPB : tile %02d, prot. %d\n", */\r
549                                                 "TPH EPB : tile %02d, part %02d, prot. %d\n",\r
550                                                 /***** tileno, */\r
551                                                 tileno, tpno,\r
552                                                 hprot\r
553                                                 );\r
554 \r
555                                         /* save this TPH EPB address */\r
556                                         tph_epb = epb_mark;\r
557 \r
558                                 } else {\r
559                                         /* ooops, problems */\r
560                                         /****** opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB #%d\n", tileno); */\r
561                                         opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not create TPH EPB in #%d,d\n", tileno, tpno);\r
562                                 };\r
563 \r
564                         }                               \r
565                 \r
566                         startpack = 0;\r
567                         /* EPB MSs for UEP packet data protection in Tile Parts */\r
568                         /****** for (packno = 0; packno < j2k->cstr_info->num; packno++) { */\r
569                         /*first_tp_pack = (tpno > 0) ? (first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno - 1].tp_numpacks) : 0;*/\r
570                         first_tp_pack = j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pack;\r
571                         last_tp_pack = first_tp_pack + j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks - 1;\r
572                         for (packno = 0; packno < j2k->cstr_info->tile[tileno].tp[tpno].tp_numpacks; packno++) {\r
573 \r
574                                 /******** if ((packspec < JPWL_MAX_NO_PACKSPECS) &&\r
575                                         (j2k->cp->pprot_tileno[packspec] == tileno) && (j2k->cp->pprot_packno[packspec] == packno)) { */\r
576                                 if ((packspec < JPWL_MAX_NO_PACKSPECS) &&\r
577                                         (j2k->cp->pprot_tileno[packspec] == acc_tpno) && (j2k->cp->pprot_packno[packspec] == packno)) {\r
578 \r
579                                         /* we got a specification from this tile and packet onwards */\r
580                                         /* print the previous spec */\r
581                                         if (packno > 0) {\r
582                                                 stoppack = packno - 1;                          \r
583                                                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
584                                                         /***** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */\r
585                                                         "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",\r
586                                                         /***** tileno, */\r
587                                                         tileno, tpno,\r
588                                                         startpack,\r
589                                                         stoppack,\r
590                                                         /***** j2k->cstr_info->tile[tileno].packet[startpack].start_pos, */\r
591                                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,\r
592                                                         /***** j2k->cstr_info->tile[tileno].packet[stoppack].end_pos, */\r
593                                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,\r
594                                                         pprot);\r
595 \r
596                                                 /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -\r
597                                                         j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */\r
598                                                 prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -\r
599                                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;\r
600 \r
601                                                 /*\r
602                                                   particular case: if this is the last header and the last packet,\r
603                                                   then it is better to protect even the EOC marker\r
604                                                 */\r
605                                                 /****** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&\r
606                                                         (stoppack == (j2k->cstr_info->num - 1))) */\r
607                                                 if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&\r
608                                                         (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&\r
609                                                         (stoppack == last_tp_pack))\r
610                                                         /* add the EOC len */\r
611                                                         prot_len += 2;\r
612 \r
613                                                 /* let's add the EPBs */\r
614                                                 Psot += jpwl_epbs_add(\r
615                                                         j2k, /* J2K handle */\r
616                                                         jwmarker, /* pointer to JPWL markers list */\r
617                                                         &jwmarker_num, /* pointer to the number of current markers */\r
618                                                         OPJ_FALSE, /* latest */\r
619                                                         OPJ_TRUE, /* packed */\r
620                                                         OPJ_FALSE, /* inside MH */\r
621                                                         &epb_index, /* pointer to EPB index */\r
622                                                         pprot, /* protection type */\r
623                                                         /****** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001, */ /* position */\r
624                                                         (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */\r
625                                                         tileno, /* number of tile */\r
626                                                         0, /* length of pre-data */\r
627                                                         prot_len /*4000*/ /* length of post-data */\r
628                                                         );\r
629                                         }\r
630 \r
631                                         startpack = packno;\r
632                                         pprot = j2k->cp->pprot[packspec++];\r
633                                 }\r
634 \r
635                                 //printf("Tile %02d, pack %02d ==> %d\n", tileno, packno, pprot);\r
636                 \r
637                         }\r
638 \r
639                         /* we are at the end: print the remaining spec */\r
640                         stoppack = packno - 1;\r
641                         if (pprot >= 0) {\r
642 \r
643                                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
644                                         /**** "UEP EPBs: tile %02d, packs. %02d-%02d (B %d-%d), prot. %d\n", */\r
645                                         "UEP EPBs: tile %02d, part %02d, packs. %02d-%02d (B %d-%d), prot. %d\n",\r
646                                         /**** tileno, */\r
647                                         tileno, tpno,\r
648                                         startpack,\r
649                                         stoppack,\r
650                                         /***** j2k->image_info->tile[tileno].packet[startpack].start_pos,\r
651                                         j2k->image_info->tile[tileno].packet[stoppack].end_pos, */\r
652                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos,\r
653                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos,\r
654                                         pprot);\r
655 \r
656                                 /***** prot_len = j2k->cstr_info->tile[tileno].packet[stoppack].end_pos + 1 -\r
657                                         j2k->cstr_info->tile[tileno].packet[startpack].start_pos; */\r
658                                 prot_len = j2k->cstr_info->tile[tileno].packet[first_tp_pack + stoppack].end_pos + 1 -\r
659                                         j2k->cstr_info->tile[tileno].packet[first_tp_pack + startpack].start_pos;\r
660 \r
661                                 /*\r
662                                   particular case: if this is the last header and the last packet,\r
663                                   then it is better to protect even the EOC marker\r
664                                 */\r
665                                 /***** if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&\r
666                                         (stoppack == (j2k->cstr_info->num - 1))) */\r
667                                 if ((tileno == ((j2k->cstr_info->tw * j2k->cstr_info->th) - 1)) &&\r
668                                         (tpno == (j2k->cstr_info->tile[tileno].num_tps - 1)) &&\r
669                                         (stoppack == last_tp_pack))\r
670                                         /* add the EOC len */\r
671                                         prot_len += 2;\r
672 \r
673                                 /* let's add the EPBs */\r
674                                 Psot += jpwl_epbs_add(\r
675                                                         j2k, /* J2K handle */\r
676                                                         jwmarker, /* pointer to JPWL markers list */\r
677                                                         &jwmarker_num, /* pointer to the number of current markers */\r
678                                                         OPJ_TRUE, /* latest */\r
679                                                         OPJ_TRUE, /* packed */\r
680                                                         OPJ_FALSE, /* inside MH */\r
681                                                         &epb_index, /* pointer to EPB index */\r
682                                                         pprot, /* protection type */\r
683                                                         /***** (double) (j2k->cstr_info->tile[tileno].start_pos + sot_len + 2) + 0.0001,*/ /* position */\r
684                                                         (double) (j2k->cstr_info->tile[tileno].tp[tpno].tp_start_pos + sot_len + 2) + 0.0001, /* position */\r
685                                                         tileno, /* number of tile */\r
686                                                         0, /* length of pre-data */\r
687                                                         prot_len /*4000*/ /* length of post-data */\r
688                                                         );\r
689                         }\r
690 \r
691                         /* we can now check if the TPH EPB was really the last one */\r
692                         if (tph_epb && (epb_index == 1)) {\r
693                                 /* set the TPH EPB to be the last one in current header */\r
694                                 tph_epb->Depb |= (unsigned char) ((OPJ_TRUE & 0x0001) << 6);\r
695                                 tph_epb = NULL;\r
696                         }\r
697 \r
698                         /* write back Psot */\r
699                         cio_seek(cio, Psotp);\r
700                         cio_write(cio, Psot, 4);\r
701                 \r
702                 }\r
703 \r
704         };\r
705 \r
706         /* reset the position */\r
707         cio_seek(cio, ciopos);\r
708 \r
709 }\r
710 \r
711 void jpwl_dump_marks(opj_j2k_t *j2k, opj_cio_t *cio, opj_image_t *image) {\r
712 \r
713         int mm;\r
714         unsigned long int old_size = j2k->cstr_info->codestream_size;\r
715         unsigned long int new_size = old_size;\r
716         int /*ciopos = cio_tell(cio),*/ soc_pos = j2k->cstr_info->main_head_start;\r
717         unsigned char *jpwl_buf, *orig_buf;\r
718         unsigned long int orig_pos;\r
719         double epbcoding_time = 0.0, esdcoding_time = 0.0;\r
720 \r
721         /* Order JPWL markers according to their wishlist position */\r
722         qsort((void *) jwmarker, (size_t) jwmarker_num, sizeof (jpwl_marker_t), jpwl_markcomp);\r
723 \r
724         /* compute markers total size */ \r
725         for (mm = 0; mm < jwmarker_num; mm++) {\r
726                 /*printf("%x, %d, %.10f, %d long\n", jwmarker[mm].id, jwmarker[mm].pos,\r
727                         jwmarker[mm].dpos, jwmarker[mm].len);*/\r
728                 new_size += jwmarker[mm].len + 2;\r
729         }\r
730 \r
731         /* allocate a new buffer of proper size */\r
732         if (!(jpwl_buf = (unsigned char *) opj_malloc((size_t) (new_size + soc_pos) * sizeof(unsigned char)))) {\r
733                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not allocate room for JPWL codestream buffer\n");\r
734                 exit(1);\r
735         };\r
736 \r
737         /* copy the jp2 part, if any */\r
738         orig_buf = jpwl_buf;\r
739         memcpy(jpwl_buf, cio->buffer, soc_pos);\r
740         jpwl_buf += soc_pos;\r
741 \r
742         /* cycle through markers */\r
743         orig_pos = soc_pos + 0; /* start from the beginning */\r
744         cio_seek(cio, soc_pos + 0); /* rewind the original */\r
745         for (mm = 0; mm < jwmarker_num; mm++) {\r
746 \r
747                 /*\r
748                 need to copy a piece of the original codestream\r
749                 if there is such\r
750                 */\r
751                 memcpy(jpwl_buf, cio_getbp(cio), jwmarker[mm].pos - orig_pos);\r
752                 jpwl_buf += jwmarker[mm].pos - orig_pos;\r
753                 orig_pos = jwmarker[mm].pos;\r
754                 cio_seek(cio, orig_pos);\r
755 \r
756                 /*\r
757                 then write down the marker\r
758                 */\r
759                 switch (jwmarker[mm].id) {\r
760 \r
761                 case J2K_MS_EPB:\r
762                         jpwl_epb_write(j2k, jwmarker[mm].m.epbmark, jpwl_buf);\r
763                         break;\r
764 \r
765                 case J2K_MS_EPC:\r
766                         jpwl_epc_write(j2k, jwmarker[mm].m.epcmark, jpwl_buf);\r
767                         break;\r
768 \r
769                 case J2K_MS_ESD:\r
770                         jpwl_esd_write(j2k, jwmarker[mm].m.esdmark, jpwl_buf);\r
771                         break;\r
772 \r
773                 case J2K_MS_RED:\r
774                         memset(jpwl_buf, 0, jwmarker[mm].len + 2); /* placeholder */\r
775                         break;\r
776 \r
777                 default:\r
778                         break;\r
779                 };\r
780 \r
781                 /* we update the markers struct */\r
782                 if (j2k->cstr_info)\r
783                         j2k->cstr_info->marker[j2k->cstr_info->marknum - 1].pos = (jpwl_buf - orig_buf);\r
784                 \r
785                 /* we set the marker dpos to the new position in the JPWL codestream */\r
786                 jwmarker[mm].dpos = (double) (jpwl_buf - orig_buf);\r
787 \r
788                 /* advance JPWL buffer position */\r
789                 jpwl_buf += jwmarker[mm].len + 2;\r
790 \r
791         }\r
792 \r
793         /* finish remaining original codestream */\r
794         memcpy(jpwl_buf, cio_getbp(cio), old_size - (orig_pos - soc_pos));\r
795         jpwl_buf += old_size - (orig_pos - soc_pos);\r
796         cio_seek(cio, soc_pos + old_size);\r
797         \r
798         /*\r
799         update info file based on added markers\r
800         */\r
801         if (!jpwl_update_info(j2k, jwmarker, jwmarker_num))\r
802                 opj_event_msg(j2k->cinfo, EVT_ERROR, "Could not update OPJ cstr_info structure\n");\r
803 \r
804         /* now we need to repass some markers and fill their data fields */\r
805         \r
806         /* first of all, DL and Pcrc in EPCs */ \r
807         for (mm = 0; mm < jwmarker_num; mm++) {\r
808 \r
809                 /* find the EPCs */\r
810                 if (jwmarker[mm].id == J2K_MS_EPC) {\r
811 \r
812                         int epc_pos = (int) jwmarker[mm].dpos, pp;\r
813                         unsigned short int mycrc = 0x0000;\r
814 \r
815                         /* fix and fill the DL field */\r
816                         jwmarker[mm].m.epcmark->DL = new_size;\r
817                         orig_buf[epc_pos + 6] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 24);\r
818                         orig_buf[epc_pos + 7] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 16);\r
819                         orig_buf[epc_pos + 8] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 8);\r
820                         orig_buf[epc_pos + 9] = (unsigned char) (jwmarker[mm].m.epcmark->DL >> 0);\r
821 \r
822                         /* compute the CRC field (excluding itself) */\r
823                         for (pp = 0; pp < 4; pp++)\r
824                                 jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);\r
825                         for (pp = 6; pp < (jwmarker[mm].len + 2); pp++)\r
826                                 jpwl_updateCRC16(&mycrc, orig_buf[epc_pos + pp]);\r
827 \r
828                         /* fix and fill the CRC */\r
829                         jwmarker[mm].m.epcmark->Pcrc = mycrc;\r
830                         orig_buf[epc_pos + 4] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 8);\r
831                         orig_buf[epc_pos + 5] = (unsigned char) (jwmarker[mm].m.epcmark->Pcrc >> 0);\r
832 \r
833                 }\r
834         }\r
835 \r
836         /* then, sensitivity data in ESDs */ \r
837         esdcoding_time = opj_clock();\r
838         for (mm = 0; mm < jwmarker_num; mm++) {\r
839 \r
840                 /* find the ESDs */\r
841                 if (jwmarker[mm].id == J2K_MS_ESD) {\r
842 \r
843                         /* remember that they are now in a new position (dpos) */\r
844                         int esd_pos = (int) jwmarker[mm].dpos;\r
845 \r
846                         jpwl_esd_fill(j2k, jwmarker[mm].m.esdmark, &orig_buf[esd_pos]);\r
847                 \r
848                 }\r
849 \r
850         }\r
851         esdcoding_time = opj_clock() - esdcoding_time;\r
852         if (j2k->cp->esd_on)\r
853                 opj_event_msg(j2k->cinfo, EVT_INFO, "ESDs sensitivities computed in %f s\n", esdcoding_time);\r
854 \r
855         /* finally, RS or CRC parity in EPBs */ \r
856         epbcoding_time = opj_clock();\r
857         for (mm = 0; mm < jwmarker_num; mm++) {\r
858 \r
859                 /* find the EPBs */\r
860                 if (jwmarker[mm].id == J2K_MS_EPB) {\r
861 \r
862                         /* remember that they are now in a new position (dpos) */\r
863                         int nn, accum_len;\r
864 \r
865                         /* let's see how many EPBs are following this one, included itself */\r
866                         /* for this to work, we suppose that the markers are correctly ordered */\r
867                         /* and, overall, that they are in packed mode inside headers */\r
868                         accum_len = 0;\r
869                         for (nn = mm; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&\r
870                                 (jwmarker[nn].pos == jwmarker[mm].pos); nn++)\r
871                                 accum_len += jwmarker[nn].m.epbmark->Lepb + 2;\r
872 \r
873                         /* fill the current (first) EPB with post-data starting from the computed position */\r
874                         jpwl_epb_fill(j2k, jwmarker[mm].m.epbmark, &orig_buf[(int) jwmarker[mm].dpos],\r
875                                 &orig_buf[(int) jwmarker[mm].dpos + accum_len]);\r
876                 \r
877                         /* fill the remaining EPBs in the header with post-data starting from the last position */\r
878                         for (nn = mm + 1; (nn < jwmarker_num) && (jwmarker[nn].id == J2K_MS_EPB) &&\r
879                                 (jwmarker[nn].pos == jwmarker[mm].pos); nn++)\r
880                                 jpwl_epb_fill(j2k, jwmarker[nn].m.epbmark, &orig_buf[(int) jwmarker[nn].dpos], NULL);\r
881 \r
882                         /* skip all the processed EPBs */\r
883                         mm = nn - 1;\r
884                 }\r
885 \r
886         }\r
887         epbcoding_time = opj_clock() - epbcoding_time;\r
888         if (j2k->cp->epb_on)\r
889                 opj_event_msg(j2k->cinfo, EVT_INFO, "EPBs redundancy computed in %f s\n", epbcoding_time);\r
890 \r
891         /* free original cio buffer and set it to the JPWL one */\r
892         opj_free(cio->buffer);\r
893         cio->cinfo = cio->cinfo; /* no change */\r
894         cio->openmode = cio->openmode; /* no change */\r
895         cio->buffer = orig_buf;\r
896         cio->length = new_size + soc_pos;\r
897         cio->start = cio->buffer;\r
898         cio->end = cio->buffer + cio->length;\r
899         cio->bp = cio->buffer;\r
900         cio_seek(cio, soc_pos + new_size);\r
901 \r
902 }\r
903 \r
904 \r
905 void j2k_read_epc(opj_j2k_t *j2k) {\r
906         unsigned long int DL, Lepcp, Pcrcp, l;\r
907         unsigned short int Lepc, Pcrc = 0x0000;\r
908         unsigned char Pepc;     \r
909         opj_cio_t *cio = j2k->cio;\r
910         const char *ans1;\r
911 \r
912         /* Simply read the EPC parameters */\r
913         Lepcp = cio_tell(cio);\r
914         Lepc = cio_read(cio, 2);\r
915         Pcrcp = cio_tell(cio);\r
916         cio_skip(cio, 2); /* Pcrc */\r
917         DL = cio_read(cio, 4);\r
918         Pepc = cio_read(cio, 1);\r
919 \r
920         /* compute Pcrc */\r
921         cio_seek(cio, Lepcp - 2);\r
922 \r
923                 /* Marker */\r
924                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
925                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
926 \r
927                 /* Length */\r
928                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
929                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
930 \r
931                 /* skip Pcrc */\r
932                 cio_skip(cio, 2);\r
933 \r
934                 /* read all remaining */\r
935                 for (l = 4; l < Lepc; l++)\r
936                         jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
937 \r
938                 /* check Pcrc with the result */\r
939                 cio_seek(cio, Pcrcp);\r
940                 ans1 = (Pcrc == (unsigned short int) cio_read(cio, 2)) ? "crc-ok" : "crc-ko";\r
941 \r
942         /* now we write them to screen */\r
943         opj_event_msg(j2k->cinfo, EVT_INFO, \r
944                 "EPC(%u,%d): %s, DL=%d%s %s %s\n",\r
945                 Lepcp - 2,\r
946                 Lepc,\r
947                 ans1,\r
948                 DL, /* data length this EPC is referring to */\r
949                 (Pepc & 0x10) ? ", esd" : "", /* ESD is present */\r
950                 (Pepc & 0x20) ? ", red" : "", /* RED is present */\r
951                 (Pepc & 0x40) ? ", epb" : ""); /* EPB is present */\r
952 \r
953         cio_seek(cio, Lepcp + Lepc);  \r
954 }\r
955 \r
956 void j2k_write_epc(opj_j2k_t *j2k) {\r
957 \r
958         unsigned long int DL, Lepcp, Pcrcp, l;\r
959         unsigned short int Lepc, Pcrc;\r
960         unsigned char Pepc;     \r
961 \r
962         opj_cio_t *cio = j2k->cio;\r
963 \r
964         cio_write(cio, J2K_MS_EPC, 2);  /* EPC */\r
965         Lepcp = cio_tell(cio);\r
966         cio_skip(cio, 2);\r
967 \r
968         /* CRC-16 word of the EPC */\r
969         Pcrc = 0x0000; /* initialize */\r
970         Pcrcp = cio_tell(cio);\r
971         cio_write(cio, Pcrc, 2); /* Pcrc placeholder*/\r
972 \r
973         /* data length of the EPC protection domain */\r
974         DL = 0x00000000; /* we leave this set to 0, as if the information is not available */\r
975         cio_write(cio, DL, 4);   /* DL */\r
976 \r
977         /* jpwl capabilities */\r
978         Pepc = 0x00;\r
979         cio_write(cio, Pepc, 1); /* Pepc */\r
980 \r
981         /* ID section */\r
982         /* no ID's, as of now */\r
983 \r
984         Lepc = (unsigned short) (cio_tell(cio) - Lepcp);\r
985         cio_seek(cio, Lepcp);\r
986         cio_write(cio, Lepc, 2); /* Lepc */\r
987 \r
988         /* compute Pcrc */\r
989         cio_seek(cio, Lepcp - 2);\r
990 \r
991                 /* Marker */\r
992                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
993                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
994 \r
995                 /* Length */\r
996                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
997                 jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
998 \r
999                 /* skip Pcrc */\r
1000                 cio_skip(cio, 2);\r
1001 \r
1002                 /* read all remaining */\r
1003                 for (l = 4; l < Lepc; l++)\r
1004                         jpwl_updateCRC16(&Pcrc, (unsigned char) cio_read(cio, 1)); \r
1005 \r
1006                 /* fill Pcrc with the result */\r
1007                 cio_seek(cio, Pcrcp);\r
1008                 cio_write(cio, Pcrc, 2);\r
1009 \r
1010         cio_seek(cio, Lepcp + Lepc);\r
1011 \r
1012         /* marker struct update */\r
1013         j2k_add_marker(j2k->cstr_info, J2K_MS_EPC, Lepcp - 2, Lepc + 2);\r
1014 \r
1015 }\r
1016 \r
1017 void j2k_read_epb(opj_j2k_t *j2k) {\r
1018         unsigned long int LDPepb, Pepb;\r
1019         unsigned short int Lepb;\r
1020         unsigned char Depb;\r
1021         char str1[25] = "";\r
1022         opj_bool status;\r
1023         static opj_bool first_in_tph = OPJ_TRUE;\r
1024         int type, pre_len, post_len;\r
1025         static unsigned char *redund = NULL;\r
1026         \r
1027         opj_cio_t *cio = j2k->cio;\r
1028 \r
1029         /* B/W = 45, RGB = 51 */\r
1030         /*           SIZ   SIZ_FIELDS     SIZ_COMPS               FOLLOWING_MARKER */\r
1031         int skipnum = 2  +     38     + 3 * j2k->cp->exp_comps  +         2;\r
1032 \r
1033         if (j2k->cp->correct) {\r
1034 \r
1035                 /* go back to EPB marker value */\r
1036                 cio_seek(cio, cio_tell(cio) - 2);\r
1037 \r
1038                 /* we need to understand where we are */\r
1039                 if (j2k->state == J2K_STATE_MH) {\r
1040                         /* we are in MH */\r
1041                         type = 0; /* MH */\r
1042                         pre_len = skipnum; /* SOC+SIZ */\r
1043                         post_len = -1; /* auto */\r
1044 \r
1045                 } else if ((j2k->state == J2K_STATE_TPH) && first_in_tph) {\r
1046                         /* we are in TPH */\r
1047                         type = 1; /* TPH */\r
1048                         pre_len = 12; /* SOC+SIZ */\r
1049                         first_in_tph = OPJ_FALSE;\r
1050                         post_len = -1; /* auto */\r
1051 \r
1052                 } else {\r
1053                         /* we are elsewhere */\r
1054                         type = 2; /* other */\r
1055                         pre_len = 0; /* nada */\r
1056                         post_len = -1; /* auto */\r
1057 \r
1058                 }\r
1059 \r
1060                 /* call EPB corrector */\r
1061                 /*printf("before %x, ", redund);*/\r
1062                 status = jpwl_epb_correct(j2k,      /* J2K decompressor handle */\r
1063                                                                   cio->bp,  /* pointer to EPB in codestream buffer */\r
1064                                                                   type,     /* EPB type: MH */\r
1065                                                                   pre_len,  /* length of pre-data */\r
1066                                                                   post_len, /* length of post-data: -1 means auto */\r
1067                                                                   NULL,     /* do everything auto */\r
1068                                                                   &redund\r
1069                                                                  );\r
1070                 /*printf("after %x\n", redund);*/\r
1071 \r
1072                 /* Read the (possibly corrected) EPB parameters */\r
1073                 cio_skip(cio, 2);\r
1074                 Lepb = cio_read(cio, 2);\r
1075                 Depb = cio_read(cio, 1);\r
1076                 LDPepb = cio_read(cio, 4);\r
1077                 Pepb = cio_read(cio, 4);\r
1078 \r
1079                 if (!status) {\r
1080 \r
1081                         opj_event_msg(j2k->cinfo, EVT_ERROR, "JPWL correction could not be performed\n");\r
1082 \r
1083                         /* advance to EPB endpoint */\r
1084                         cio_skip(cio, Lepb + 2);  \r
1085 \r
1086                         return;\r
1087                 }\r
1088 \r
1089                 /* last in current header? */\r
1090                 if (Depb & 0x40) {\r
1091                         redund = NULL; /* reset the pointer to L4 buffer */\r
1092                         first_in_tph = OPJ_TRUE;\r
1093                 }\r
1094 \r
1095                 /* advance to EPB endpoint */\r
1096                 cio_skip(cio, Lepb - 11);  \r
1097 \r
1098         } else {\r
1099 \r
1100                 /* Simply read the EPB parameters */\r
1101                 Lepb = cio_read(cio, 2);\r
1102                 Depb = cio_read(cio, 1);\r
1103                 LDPepb = cio_read(cio, 4);\r
1104                 Pepb = cio_read(cio, 4);\r
1105 \r
1106                 /* What does Pepb tells us about the protection method? */\r
1107                 if (((Pepb & 0xF0000000) >> 28) == 0)\r
1108                         sprintf(str1, "pred"); /* predefined */\r
1109                 else if (((Pepb & 0xF0000000) >> 28) == 1)\r
1110                         sprintf(str1, "crc-%lu", 16 * ((Pepb & 0x00000001) + 1)); /* CRC mode */\r
1111                 else if (((Pepb & 0xF0000000) >> 28) == 2)\r
1112                         sprintf(str1, "rs(%lu,32)", (Pepb & 0x0000FF00) >> 8); /* RS mode */\r
1113                 else if (Pepb == 0xFFFFFFFF)\r
1114                         sprintf(str1, "nometh"); /* RS mode */\r
1115                 else\r
1116                         sprintf(str1, "unknown"); /* unknown */\r
1117 \r
1118                 /* Now we write them to screen */\r
1119                 opj_event_msg(j2k->cinfo, EVT_INFO,\r
1120                         "EPB(%d): (%sl, %sp, %u), %lu, %s\n",\r
1121                         cio_tell(cio) - 13,\r
1122                         (Depb & 0x40) ? "" : "n", /* latest EPB or not? */\r
1123                         (Depb & 0x80) ? "" : "n", /* packed or unpacked EPB? */\r
1124                         (Depb & 0x3F), /* EPB index value */\r
1125                         LDPepb, /*length of the data protected by the EPB */\r
1126                         str1); /* protection method */\r
1127 \r
1128                 cio_skip(cio, Lepb - 11);  \r
1129         }\r
1130 }\r
1131 \r
1132 void j2k_write_epb(opj_j2k_t *j2k) {\r
1133         unsigned long int LDPepb, Pepb, Lepbp;\r
1134         unsigned short int Lepb;\r
1135         unsigned char Depb;\r
1136 \r
1137         opj_cio_t *cio = j2k->cio;\r
1138 \r
1139         cio_write(cio, J2K_MS_EPB, 2);  /* EPB */\r
1140         Lepbp = cio_tell(cio);\r
1141         cio_skip(cio, 2);\r
1142 \r
1143         /* EPB style */\r
1144         Depb = 0x00; /* test */\r
1145         cio_write(cio, Depb, 1);   /* Depb */\r
1146 \r
1147         /* length of the data to be protected by this EPB */\r
1148         LDPepb = 0x00000000; /* test */\r
1149         cio_write(cio, LDPepb, 4);   /* LDPepb */\r
1150 \r
1151         /* next error correction tool */\r
1152         Pepb = 0x00000000; /* test */\r
1153         cio_write(cio, Pepb, 4);   /* Pepb */\r
1154 \r
1155         /* EPB data */\r
1156         /* no data, as of now */\r
1157 \r
1158         Lepb = (unsigned short) (cio_tell(cio) - Lepbp);\r
1159         cio_seek(cio, Lepbp);\r
1160         cio_write(cio, Lepb, 2);                /* Lepb */\r
1161 \r
1162         cio_seek(cio, Lepbp + Lepb);\r
1163 \r
1164         /* marker struct update */\r
1165         j2k_add_marker(j2k->cstr_info, J2K_MS_EPB, Lepbp - 2, Lepb + 2);\r
1166 }\r
1167 \r
1168 void j2k_read_esd(opj_j2k_t *j2k) {\r
1169         unsigned short int Lesd, Cesd;\r
1170         unsigned char Pesd;\r
1171 \r
1172         int cesdsize = (j2k->image->numcomps >= 257) ? 2 : 1;\r
1173 \r
1174         char str1[4][4] = {"p", "br", "pr", "res"};\r
1175         char str2[8][8] = {"res", "mse", "mse-r", "psnr", "psnr-i", "maxerr", "tse", "res"};\r
1176         \r
1177         opj_cio_t *cio = j2k->cio;\r
1178 \r
1179         /* Simply read the ESD parameters */\r
1180         Lesd = cio_read(cio, 2);\r
1181         Cesd = cio_read(cio, cesdsize);\r
1182         Pesd = cio_read(cio, 1);\r
1183 \r
1184         /* Now we write them to screen */\r
1185         opj_event_msg(j2k->cinfo, EVT_INFO,\r
1186                 "ESD(%d): c%d, %s, %s, %s, %s, %s\n",\r
1187                 cio_tell(cio) - (5 + cesdsize),\r
1188                 Cesd, /* component number for this ESD */\r
1189                 str1[(Pesd & (unsigned char) 0xC0) >> 6], /* addressing mode */\r
1190                 str2[(Pesd & (unsigned char) 0x38) >> 3], /* sensitivity type */\r
1191                 ((Pesd & (unsigned char) 0x04) >> 2) ? "2Bs" : "1Bs",\r
1192                 ((Pesd & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba",\r
1193                 (Pesd & (unsigned char) 0x01) ? "avgc" : "");\r
1194 \r
1195         cio_skip(cio, Lesd - (3 + cesdsize));  \r
1196 }\r
1197 \r
1198 void j2k_read_red(opj_j2k_t *j2k) {\r
1199         unsigned short int Lred;\r
1200         unsigned char Pred;\r
1201         char str1[4][4] = {"p", "br", "pr", "res"};\r
1202         \r
1203         opj_cio_t *cio = j2k->cio;\r
1204 \r
1205         /* Simply read the RED parameters */\r
1206         Lred = cio_read(cio, 2);\r
1207         Pred = cio_read(cio, 1);\r
1208 \r
1209         /* Now we write them to screen */\r
1210         opj_event_msg(j2k->cinfo, EVT_INFO,\r
1211                 "RED(%d): %s, %dc, %s, %s\n",\r
1212                 cio_tell(cio) - 5,\r
1213                 str1[(Pred & (unsigned char) 0xC0) >> 6], /* addressing mode */\r
1214                 (Pred & (unsigned char) 0x38) >> 3, /* corruption level */\r
1215                 ((Pred & (unsigned char) 0x02) >> 1) ? "4Ba" : "2Ba", /* address range */\r
1216                 (Pred & (unsigned char) 0x01) ? "errs" : "free"); /* error free? */\r
1217 \r
1218         cio_skip(cio, Lred - 3);  \r
1219 }\r
1220 \r
1221 opj_bool jpwl_check_tile(opj_j2k_t *j2k, opj_tcd_t *tcd, int tileno) {\r
1222 \r
1223 #ifdef oerhgierhgvhreit4u\r
1224         /*\r
1225            we navigate through the tile and find possible invalid parameters:\r
1226        this saves a lot of crashes!!!!!\r
1227          */\r
1228         int compno, resno, precno, /*layno,*/ bandno, blockno;\r
1229         int numprecincts, numblocks;\r
1230 \r
1231         /* this is the selected tile */\r
1232         opj_tcd_tile_t *tile = &(tcd->tcd_image->tiles[tileno]);\r
1233 \r
1234         /* will keep the component */\r
1235         opj_tcd_tilecomp_t *comp = NULL;\r
1236 \r
1237         /* will keep the resolution */\r
1238         opj_tcd_resolution_t *res;\r
1239 \r
1240         /* will keep the subband */\r
1241         opj_tcd_band_t *band; \r
1242 \r
1243         /* will keep the precinct */\r
1244         opj_tcd_precinct_t *prec; \r
1245 \r
1246         /* will keep the codeblock */\r
1247         opj_tcd_cblk_t *block;\r
1248 \r
1249         /* check all tile components */\r
1250         for (compno = 0; compno < tile->numcomps; compno++) {\r
1251                 comp = &(tile->comps[compno]);\r
1252 \r
1253                 /* check all component resolutions */\r
1254                 for (resno = 0; resno < comp->numresolutions; resno++) {\r
1255                         res = &(comp->resolutions[resno]);\r
1256                         numprecincts = res->pw * res->ph;\r
1257 \r
1258                         /* check all the subbands */\r
1259                         for (bandno = 0; bandno < res->numbands; bandno++) {\r
1260                                 band = &(res->bands[bandno]);\r
1261 \r
1262                                 /* check all the precincts */\r
1263                                 for (precno = 0; precno < numprecincts; precno++) {\r
1264                                         prec = &(band->precincts[precno]);\r
1265                                         numblocks = prec->ch * prec->cw;\r
1266 \r
1267                                         /* check all the codeblocks */\r
1268                                         for (blockno = 0; blockno < numblocks; blockno++) {\r
1269                                                 block = &(prec->cblks[blockno]);\r
1270 \r
1271                                                 /* x-origin is invalid */\r
1272                                                 if ((block->x0 < prec->x0) || (block->x0 > prec->x1)) {\r
1273                                                         opj_event_msg(j2k->cinfo, JPWL_ASSUME ? EVT_WARNING : EVT_ERROR,\r
1274                                                                 "JPWL: wrong x-cord of block origin %d => x-prec is (%d, %d)\n",\r
1275                                                                 block->x0, prec->x0, prec->x1);\r
1276                                                         if (!JPWL_ASSUME || JPWL_ASSUME)\r
1277                                                                 return OPJ_FALSE;\r
1278                                                 };\r
1279                                         }\r
1280                                 }                               \r
1281                         }\r
1282                 }\r
1283         }\r
1284 \r
1285 #endif\r
1286 \r
1287         return OPJ_TRUE;\r
1288 }\r
1289 \r
1290 /*@}*/\r
1291 \r
1292 #endif /* USE_JPWL */\r
1293 \r
1294 \r
1295 #ifdef USE_JPSEC\r
1296 \r
1297 /** @defgroup JPSEC JPSEC - JPEG-2000 Part 8 (JPSEC) codestream manager */\r
1298 /*@{*/\r
1299 \r
1300 \r
1301 /** @name Local static functions */\r
1302 /*@{*/\r
1303 \r
1304 void j2k_read_sec(opj_j2k_t *j2k) {\r
1305         unsigned short int Lsec;\r
1306         \r
1307         opj_cio_t *cio = j2k->cio;\r
1308 \r
1309         /* Simply read the SEC length */\r
1310         Lsec = cio_read(cio, 2);\r
1311 \r
1312         /* Now we write them to screen */\r
1313         opj_event_msg(j2k->cinfo, EVT_INFO,\r
1314                 "SEC(%d)\n",\r
1315                 cio_tell(cio) - 2\r
1316                 );\r
1317 \r
1318         cio_skip(cio, Lsec - 2);  \r
1319 }\r
1320 \r
1321 void j2k_write_sec(opj_j2k_t *j2k) {\r
1322         unsigned short int Lsec = 24;\r
1323         int i;\r
1324 \r
1325         opj_cio_t *cio = j2k->cio;\r
1326 \r
1327         cio_write(cio, J2K_MS_SEC, 2);  /* SEC */\r
1328         cio_write(cio, Lsec, 2);\r
1329 \r
1330         /* write dummy data */\r
1331         for (i = 0; i < Lsec - 2; i++)\r
1332                 cio_write(cio, 0, 1);\r
1333 }\r
1334 \r
1335 void j2k_read_insec(opj_j2k_t *j2k) {\r
1336         unsigned short int Linsec;\r
1337         \r
1338         opj_cio_t *cio = j2k->cio;\r
1339 \r
1340         /* Simply read the INSEC length */\r
1341         Linsec = cio_read(cio, 2);\r
1342 \r
1343         /* Now we write them to screen */\r
1344         opj_event_msg(j2k->cinfo, EVT_INFO,\r
1345                 "INSEC(%d)\n",\r
1346                 cio_tell(cio) - 2\r
1347                 );\r
1348 \r
1349         cio_skip(cio, Linsec - 2);  \r
1350 }\r
1351 \r
1352 \r
1353 /*@}*/\r
1354 \r
1355 /*@}*/\r
1356 \r
1357 #endif /* USE_JPSEC */\r
1358 \r