001/* 002 * $RCSfile: PktDecoder.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:01 $ 005 * $State: Exp $ 006 * 007 * Class: PktDecoder 008 * 009 * Description: Reads packets heads and keeps location of 010 * code-blocks' codewords 011 * 012 * 013 * 014 * COPYRIGHT: 015 * 016 * This software module was originally developed by Raphaël Grosbois and 017 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel 018 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David 019 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research 020 * Centre France S.A) in the course of development of the JPEG2000 021 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This 022 * software module is an implementation of a part of the JPEG 2000 023 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio 024 * Systems AB and Canon Research Centre France S.A (collectively JJ2000 025 * Partners) agree not to assert against ISO/IEC and users of the JPEG 026 * 2000 Standard (Users) any of their rights under the copyright, not 027 * including other intellectual property rights, for this software module 028 * with respect to the usage by ISO/IEC and Users of this software module 029 * or modifications thereof for use in hardware or software products 030 * claiming conformance to the JPEG 2000 Standard. Those intending to use 031 * this software module in hardware or software products are advised that 032 * their use may infringe existing patents. The original developers of 033 * this software module, JJ2000 Partners and ISO/IEC assume no liability 034 * for use of this software module or modifications thereof. No license 035 * or right to this software module is granted for non JPEG 2000 Standard 036 * conforming products. JJ2000 Partners have full right to use this 037 * software module for his/her own purpose, assign or donate this 038 * software module to any third party and to inhibit third parties from 039 * using this software module for non JPEG 2000 Standard conforming 040 * products. This copyright notice must be included in all copies or 041 * derivative works of this software module. 042 * 043 * Copyright (c) 1999/2000 JJ2000 Partners. 044 * */ 045package jj2000.j2k.codestream.reader; 046import java.awt.Point; 047 048import jj2000.j2k.wavelet.synthesis.*; 049import jj2000.j2k.codestream.*; 050import jj2000.j2k.entropy.*; 051import jj2000.j2k.wavelet.*; 052import jj2000.j2k.decoder.*; 053import jj2000.j2k.image.*; 054import jj2000.j2k.util.*; 055import jj2000.j2k.io.*; 056 057import java.util.*; 058import java.io.*; 059 060/** 061 * This class is used to read packet's head and body. All the members must be 062 * re-initialized at the beginning of each tile thanks to the restart() 063 * method. 064 * */ 065public class PktDecoder implements StdEntropyCoderOptions{ 066 067 /** Reference to the codestream reader agent */ 068 private BitstreamReaderAgent src; 069 070 /** Flag indicating whether packed packet header was used for this tile*/ 071 private boolean pph=false; 072 073 /** The packed packet header if it was used */ 074 private ByteArrayInputStream pphbais; 075 076 /** Reference to decoder specifications */ 077 private DecoderSpecs decSpec; 078 079 /** Reference to the HeaderDecoder */ 080 private HeaderDecoder hd; 081 082 /** Initial value of the state variable associated with code-block 083 * length. */ 084 private final int INIT_LBLOCK = 3; 085 086 /** The wrapper to read bits for the packet heads */ 087 private PktHeaderBitReader bin; 088 089 /** Reference to the stream where to read from */ 090 private RandomAccessIO ehs; 091 092 /** 093 * Maximum number of precincts : 094 * 095 * <ul> 096 * <li> 1st dim: component index.</li> 097 * <li> 2nd dim: resolution level index.</li> 098 * </ul> 099 * */ 100 private Point[][] numPrec; 101 102 /** Index of the current tile */ 103 private int tIdx; 104 105 /** 106 * Array containing the coordinates, width, height, indexes, ... of the 107 * precincts in the current tile: 108 * 109 * <ul> 110 * <li> 1st dim: component index.</li> 111 * <li> 2nd dim: resolution level index.</li> 112 * <li> 3rd dim: precinct index.</li> 113 * </ul> 114 * */ 115 private PrecInfo[][][] ppinfo; 116 117 /** 118 * Lblock value used to read code size information in each packet head: 119 * 120 * <ul> 121 * <li> 1st dim: component index.</li> 122 * <li> 2nd dim: resolution level index.</li> 123 * <li> 3rd dim: subband index.</li> 124 * <li> 4th/5th dim: code-block index (vert. and horiz.).</li> 125 * </ul> 126 * */ 127 private int[][][][][] lblock; 128 129 /** 130 * Tag tree used to read inclusion informations in packet's head: 131 * 132 * <ul> 133 * <li> 1st dim: component index.</li> 134 * <li> 2nd dim: resolution level index.</li> 135 * <li> 3rd dim: precinct index.</li> 136 * <li> 4th dim: subband index.</li> 137 * */ 138 private TagTreeDecoder[][][][] ttIncl; 139 140 /** 141 * Tag tree used to read bit-depth information in packet's head: 142 * 143 * <ul> 144 * <li> 1st dim: component index.</li> 145 * <li> 2nd dim: resolution level index.</li> 146 * <li> 3rd dim: precinct index.</li> 147 * <li> 4th dim: subband index.</li> 148 * </ul> 149 * */ 150 private TagTreeDecoder[][][][] ttMaxBP; 151 152 /** Number of layers in t he current tile */ 153 private int nl = 0; 154 155 /** The number of components */ 156 private int nc; 157 158 /** Whether or not SOP marker segment are used */ 159 private boolean sopUsed = false; 160 161 /** Whether or not EPH marker are used */ 162 private boolean ephUsed = false; 163 164 /** Index of the current packet in the tile. Used with SOP marker 165 segment*/ 166 private int pktIdx; 167 168 /** List of code-blocks found in last read packet head (one list 169 * per subband) */ 170 private Vector[] cblks; 171 172 /** Number of codeblocks encountered. used for ncb quit condition*/ 173 private int ncb; 174 175 /** Maximum number of codeblocks to read before ncb quit condition is 176 * reached */ 177 private int maxCB; 178 179 /** Flag indicating whether ncb quit condition has been reached */ 180 private boolean ncbQuit; 181 182 /** The tile in which the ncb quit condition was reached */ 183 private int tQuit; 184 185 /** The component in which the ncb quit condition was reached */ 186 private int cQuit; 187 188 /** The subband in which the ncb quit condition was reached */ 189 private int sQuit; 190 191 /** The resolution in which the ncb quit condition was reached */ 192 private int rQuit; 193 194 /** The x position of the last code block before ncb quit reached */ 195 private int xQuit; 196 197 /** The y position of the last code block before ncb quit reached */ 198 private int yQuit; 199 200 /** True if truncation mode is used. False if it is parsing mode */ 201 private boolean isTruncMode; 202 203 /** 204 * Creates an empty PktDecoder object associated with given decoder 205 * specifications and HeaderDecoder. This object must be initialized 206 * thanks to the restart method before being used. 207 * 208 * @param decSpec The decoder specifications. 209 * 210 * @param hd The HeaderDecoder instance. 211 * 212 * @param ehs The stream where to read data from. 213 * 214 * @param src The bit stream reader agent. 215 * 216 * @param isTruncMode Whether or not truncation mode is required. 217 * 218 * @param maxCB The maximum number of code-blocks to read before ncbquit 219 * 220 * */ 221 public PktDecoder(DecoderSpecs decSpec,HeaderDecoder hd, 222 RandomAccessIO ehs,BitstreamReaderAgent src, 223 boolean isTruncMode, int maxCB) { 224 this.decSpec = decSpec; 225 this.hd = hd; 226 this.ehs = ehs; 227 this.isTruncMode = isTruncMode; 228 bin = new PktHeaderBitReader(ehs); 229 this.src = src; 230 ncb = 0; 231 ncbQuit = false; 232 this.maxCB = maxCB; 233 } 234 235 /** 236 * Re-initialize the PktDecoder instance at the beginning of a new tile. 237 * 238 * @param nc The number of components in this tile 239 * 240 * @param mdl The maximum number of decomposition level in each component 241 * of this tile 242 * 243 * @param nl The number of layers in this tile 244 * 245 * @param cbI The code-blocks array 246 * 247 * @param pph Flag indicating whether packed packet headers was used 248 * 249 * @param pphbais Stream containing the packed packet headers 250 * */ 251 public CBlkInfo[][][][][] restart(int nc,int[] mdl,int nl, 252 CBlkInfo[][][][][] cbI, boolean pph, 253 ByteArrayInputStream pphbais) { 254 this.nc = nc; 255 this.nl = nl; 256 this.tIdx = src.getTileIdx(); 257 this.pph = pph; 258 this.pphbais = pphbais; 259 260 sopUsed = ((Boolean)decSpec.sops.getTileDef(tIdx)).booleanValue(); 261 pktIdx = 0; 262 ephUsed = ((Boolean)decSpec.ephs.getTileDef(tIdx)).booleanValue(); 263 264 cbI = new CBlkInfo[nc][][][][]; 265 lblock = new int[nc][][][][]; 266 ttIncl = new TagTreeDecoder[nc][][][]; 267 ttMaxBP = new TagTreeDecoder[nc][][][]; 268 numPrec = new Point[nc][]; 269 ppinfo = new PrecInfo[nc][][]; 270 271 // Used to compute the maximum number of precincts for each resolution 272 // level 273 int tcx0, tcy0, tcx1, tcy1; // Current tile position in the domain of 274 // the image component 275 int trx0, try0, trx1, try1; // Current tile position in the reduced 276 // resolution image domain 277 int xrsiz, yrsiz; // Component sub-sampling factors 278 279 SubbandSyn root,sb; 280 int mins,maxs; 281 Point nBlk = null; 282 int cb0x = src.getCbULX(); 283 int cb0y = src.getCbULY(); 284 285 for(int c=0; c<nc; c++) { 286 cbI[c] = new CBlkInfo[mdl[c]+1][][][]; 287 lblock[c] = new int[mdl[c]+1][][][]; 288 ttIncl[c] = new TagTreeDecoder[mdl[c]+1][][]; 289 ttMaxBP[c] = new TagTreeDecoder[mdl[c]+1][][]; 290 numPrec[c] = new Point[mdl[c]+1]; 291 ppinfo[c] = new PrecInfo[mdl[c]+1][]; 292 293 // Get the tile-component coordinates on the reference grid 294 tcx0 = src.getResULX(c,mdl[c]); 295 tcy0 = src.getResULY(c,mdl[c]); 296 tcx1 = tcx0 + src.getTileCompWidth(tIdx,c,mdl[c]); 297 tcy1 = tcy0 + src.getTileCompHeight(tIdx,c,mdl[c]); 298 299 for(int r=0; r<=mdl[c]; r++) { 300 301 // Tile's coordinates in the reduced resolution image domain 302 trx0 = (int)Math.ceil(tcx0/(double)(1<<(mdl[c]-r))); 303 try0 = (int)Math.ceil(tcy0/(double)(1<<(mdl[c]-r))); 304 trx1 = (int)Math.ceil(tcx1/(double)(1<<(mdl[c]-r))); 305 try1 = (int)Math.ceil(tcy1/(double)(1<<(mdl[c]-r))); 306 307 // Calculate the maximum number of precincts for each 308 // resolution level taking into account tile specific options. 309 double twoppx = (double)getPPX(tIdx,c,r); 310 double twoppy = (double)getPPY(tIdx,c,r); 311 numPrec[c][r] = new Point(); 312 if (trx1>trx0) { 313 numPrec[c][r].x = (int)Math.ceil((trx1-cb0x)/twoppx) 314 - (int)Math.floor((trx0-cb0x)/twoppx); 315 } else { 316 numPrec[c][r].x = 0; 317 } 318 if (try1>try0) { 319 numPrec[c][r].y = (int)Math.ceil((try1-cb0y)/twoppy) 320 - (int)Math.floor((try0-cb0y)/twoppy); 321 } else { 322 numPrec[c][r].y = 0; 323 } 324 325 // First and last subbands indexes 326 mins = (r==0) ? 0 : 1; 327 maxs = (r==0) ? 1 : 4; 328 329 int maxPrec = numPrec[c][r].x * numPrec[c][r].y; 330 331 ttIncl[c][r] = new TagTreeDecoder[maxPrec][maxs+1]; 332 ttMaxBP[c][r] = new TagTreeDecoder[maxPrec][maxs+1]; 333 cbI[c][r] = new CBlkInfo[maxs+1][][]; 334 lblock[c][r] = new int[maxs+1][][]; 335 336 ppinfo[c][r] = new PrecInfo[maxPrec]; 337 fillPrecInfo(c,r,mdl[c]); 338 339 root = (SubbandSyn)src.getSynSubbandTree(tIdx,c); 340 for(int s=mins; s<maxs; s++){ 341 sb = (SubbandSyn)root.getSubbandByIdx(r,s); 342 nBlk = sb.numCb; 343 344 cbI[c][r][s] = new CBlkInfo[nBlk.y][nBlk.x]; 345 lblock[c][r][s] = new int[nBlk.y][nBlk.x]; 346 347 for(int i=nBlk.y-1;i>=0;i--) { 348 ArrayUtil.intArraySet(lblock[c][r][s][i],INIT_LBLOCK); 349 } 350 } // loop on subbands 351 } // End loop on resolution levels 352 } // End loop on components 353 354 return cbI; 355 } 356 357 /** 358 * Retrives precincts and code-blocks coordinates in the given resolution, 359 * level and component. Finishes TagTreeEncoder initialization as well. 360 * 361 * @param c Component index. 362 * 363 * @param r Resolution level index. 364 * 365 * @param mdl Number of decomposition level in component <tt>c</tt>. 366 * */ 367 private void fillPrecInfo(int c,int r,int mdl) { 368 if(ppinfo[c][r].length==0) return; // No precinct in this 369 // resolution level 370 371 Point tileI = src.getTile(null); 372 Point nTiles = src.getNumTiles(null); 373 374 int xsiz,ysiz,x0siz,y0siz; 375 int xt0siz,yt0siz; 376 int xtsiz,ytsiz; 377 378 xt0siz = src.getTilePartULX(); 379 yt0siz = src.getTilePartULY(); 380 xtsiz = src.getNomTileWidth(); 381 ytsiz = src.getNomTileHeight(); 382 x0siz = hd.getImgULX(); 383 y0siz = hd.getImgULY(); 384 xsiz = hd.getImgWidth(); 385 ysiz = hd.getImgHeight(); 386 387 int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 388 int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 389 int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 390 int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 391 392 int xrsiz = hd.getCompSubsX(c); 393 int yrsiz = hd.getCompSubsY(c); 394 395 int tcx0 = src.getResULX(c,mdl); 396 int tcy0 = src.getResULY(c,mdl); 397 int tcx1 = tcx0 + src.getTileCompWidth(tIdx,c,mdl); 398 int tcy1 = tcy0 + src.getTileCompHeight(tIdx,c,mdl); 399 400 int ndl = mdl-r; 401 int trx0 = (int)Math.ceil(tcx0/(double)(1<<ndl)); 402 int try0 = (int)Math.ceil(tcy0/(double)(1<<ndl)); 403 int trx1 = (int)Math.ceil(tcx1/(double)(1<<ndl)); 404 int try1 = (int)Math.ceil(tcy1/(double)(1<<ndl)); 405 406 int cb0x = src.getCbULX(); 407 int cb0y = src.getCbULY(); 408 409 double twoppx = (double)getPPX(tIdx,c,r); 410 double twoppy = (double)getPPY(tIdx,c,r); 411 int twoppx2 = (int)(twoppx/2); 412 int twoppy2 = (int)(twoppy/2); 413 414 // Precincts are located at (cb0x+i*twoppx,cb0y+j*twoppy) 415 // Valid precincts are those which intersect with the current 416 // resolution level 417 int maxPrec = ppinfo[c][r].length; 418 int nPrec = 0; 419 420 int istart = (int)Math.floor((try0-cb0y)/twoppy); 421 int iend = (int)Math.floor((try1-1-cb0y)/twoppy); 422 int jstart = (int)Math.floor((trx0-cb0x)/twoppx); 423 int jend = (int)Math.floor((trx1-1-cb0x)/twoppx); 424 425 int acb0x,acb0y; 426 427 SubbandSyn root = src.getSynSubbandTree(tIdx,c); 428 SubbandSyn sb = null; 429 430 int p0x,p0y,p1x,p1y; // Precinct projection in subband 431 int s0x,s0y,s1x,s1y; // Active subband portion 432 int cw,ch; 433 int kstart,kend,lstart,lend,k0,l0; 434 int prg_ulx,prg_uly; 435 int prg_w = (int)twoppx<<ndl; 436 int prg_h = (int)twoppy<<ndl; 437 int tmp1,tmp2; 438 439 CBlkCoordInfo cb; 440 441 for(int i=istart; i<=iend; i++) { // Vertical precincts 442 for(int j=jstart; j<=jend; j++,nPrec++) { // Horizontal precincts 443 if(j==jstart && (trx0-cb0x)%(xrsiz*((int)twoppx))!=0) { 444 prg_ulx = tx0; 445 } else { 446 prg_ulx = cb0x+j*xrsiz*((int)twoppx<<ndl); 447 } 448 if(i==istart && (try0-cb0y)%(yrsiz*((int)twoppy))!=0) { 449 prg_uly = ty0; 450 } else { 451 prg_uly = cb0y+i*yrsiz*((int)twoppy<<ndl); 452 } 453 454 ppinfo[c][r][nPrec] = 455 new PrecInfo(r,(int)(cb0x+j*twoppx),(int)(cb0y+i*twoppy), 456 (int)twoppx,(int)twoppy, 457 prg_ulx,prg_uly,prg_w,prg_h); 458 459 if(r==0) { // LL subband 460 acb0x = cb0x; 461 acb0y = cb0y; 462 463 p0x = acb0x+j*(int)twoppx; 464 p1x = p0x + (int)twoppx; 465 p0y = acb0y+i*(int)twoppy; 466 p1y = p0y + (int)twoppy; 467 468 sb = (SubbandSyn)root.getSubbandByIdx(0,0); 469 s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x; 470 s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; 471 s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y; 472 s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; 473 474 // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) 475 cw = sb.nomCBlkW; 476 ch = sb.nomCBlkH; 477 k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); 478 kstart = (int)Math.floor((s0y-acb0y)/(double)ch); 479 kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); 480 l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); 481 lstart = (int)Math.floor((s0x-acb0x)/(double)cw); 482 lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); 483 484 if(s1x-s0x<=0 || s1y-s0y<=0) { 485 ppinfo[c][r][nPrec].nblk[0] = 0; 486 ttIncl[c][r][nPrec][0] = new TagTreeDecoder(0,0); 487 ttMaxBP[c][r][nPrec][0] = new TagTreeDecoder(0,0); 488 } else { 489 ttIncl[c][r][nPrec][0] = 490 new TagTreeDecoder(kend-kstart+1,lend-lstart+1); 491 ttMaxBP[c][r][nPrec][0] = 492 new TagTreeDecoder(kend-kstart+1,lend-lstart+1); 493 ppinfo[c][r][nPrec].cblk[0] = 494 new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; 495 ppinfo[c][r][nPrec]. 496 nblk[0] = (kend-kstart+1)*(lend-lstart+1); 497 498 for(int k=kstart; k<=kend; k++) { // Vertical cblks 499 for(int l=lstart; l<=lend; l++) { // Horiz. cblks 500 cb = new CBlkCoordInfo(k-k0,l-l0); 501 if(l==l0) { 502 cb.ulx = sb.ulx; 503 } else { 504 cb.ulx = sb.ulx+l*cw-(sb.ulcx-acb0x); 505 } 506 if(k==k0) { 507 cb.uly = sb.uly; 508 } else { 509 cb.uly = sb.uly+k*ch-(sb.ulcy-acb0y); 510 } 511 tmp1 = acb0x+l*cw; 512 tmp1 = (tmp1>sb.ulcx) ? tmp1 : sb.ulcx; 513 tmp2 = acb0x+(l+1)*cw; 514 tmp2 = (tmp2>sb.ulcx+sb.w) ? 515 sb.ulcx+sb.w : tmp2; 516 cb.w = tmp2-tmp1; 517 tmp1 = acb0y+k*ch; 518 tmp1 = (tmp1>sb.ulcy) ? tmp1 : sb.ulcy; 519 tmp2 = acb0y+(k+1)*ch; 520 tmp2 = (tmp2>sb.ulcy+sb.h) ? 521 sb.ulcy+sb.h : tmp2; 522 cb.h = tmp2-tmp1; 523 ppinfo[c][r][nPrec]. 524 cblk[0][k-kstart][l-lstart] = cb; 525 } // Horizontal code-blocks 526 } // Vertical code-blocks 527 } 528 } else { // HL, LH and HH subbands 529 // HL subband 530 acb0x = 0; 531 acb0y = cb0y; 532 533 p0x = acb0x+j*twoppx2; 534 p1x = p0x + twoppx2; 535 p0y = acb0y+i*twoppy2; 536 p1y = p0y + twoppy2; 537 538 sb = (SubbandSyn)root.getSubbandByIdx(r,1); 539 s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x; 540 s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; 541 s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y; 542 s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; 543 544 // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) 545 cw = sb.nomCBlkW; 546 ch = sb.nomCBlkH; 547 k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); 548 kstart = (int)Math.floor((s0y-acb0y)/(double)ch); 549 kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); 550 l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); 551 lstart = (int)Math.floor((s0x-acb0x)/(double)cw); 552 lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); 553 554 if(s1x-s0x<=0 || s1y-s0y<=0) { 555 ppinfo[c][r][nPrec].nblk[1] = 0; 556 ttIncl[c][r][nPrec][1] = new TagTreeDecoder(0,0); 557 ttMaxBP[c][r][nPrec][1] = new TagTreeDecoder(0,0); 558 } else { 559 ttIncl[c][r][nPrec][1] = 560 new TagTreeDecoder(kend-kstart+1,lend-lstart+1); 561 ttMaxBP[c][r][nPrec][1] = 562 new TagTreeDecoder(kend-kstart+1,lend-lstart+1); 563 ppinfo[c][r][nPrec].cblk[1] = 564 new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; 565 ppinfo[c][r][nPrec]. 566 nblk[1] = (kend-kstart+1)*(lend-lstart+1); 567 568 for(int k=kstart; k<=kend; k++) { // Vertical cblks 569 for(int l=lstart; l<=lend; l++) { // Horiz. cblks 570 cb = new CBlkCoordInfo(k-k0,l-l0); 571 if(l==l0) { 572 cb.ulx = sb.ulx; 573 } else { 574 cb.ulx = sb.ulx+l*cw-(sb.ulcx-acb0x); 575 } 576 if(k==k0) { 577 cb.uly = sb.uly; 578 } else { 579 cb.uly = sb.uly+k*ch-(sb.ulcy-acb0y); 580 } 581 tmp1 = acb0x+l*cw; 582 tmp1 = (tmp1>sb.ulcx) ? tmp1 : sb.ulcx; 583 tmp2 = acb0x+(l+1)*cw; 584 tmp2 = (tmp2>sb.ulcx+sb.w) ? 585 sb.ulcx+sb.w : tmp2; 586 cb.w = tmp2-tmp1; 587 tmp1 = acb0y+k*ch; 588 tmp1 = (tmp1>sb.ulcy) ? tmp1 : sb.ulcy; 589 tmp2 = acb0y+(k+1)*ch; 590 tmp2 = (tmp2>sb.ulcy+sb.h) ? 591 sb.ulcy+sb.h : tmp2; 592 cb.h = tmp2-tmp1; 593 ppinfo[c][r][nPrec]. 594 cblk[1][k-kstart][l-lstart] = cb; 595 } // Horizontal code-blocks 596 } // Vertical code-blocks 597 } 598 599 // LH subband 600 acb0x = cb0x; 601 acb0y = 0; 602 603 p0x = acb0x+j*twoppx2; 604 p1x = p0x + twoppx2; 605 p0y = acb0y+i*twoppy2; 606 p1y = p0y + twoppy2; 607 608 sb = (SubbandSyn)root.getSubbandByIdx(r,2); 609 s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x; 610 s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; 611 s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y; 612 s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; 613 614 // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) 615 cw = sb.nomCBlkW; 616 ch = sb.nomCBlkH; 617 k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); 618 kstart = (int)Math.floor((s0y-acb0y)/(double)ch); 619 kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); 620 l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); 621 lstart = (int)Math.floor((s0x-acb0x)/(double)cw); 622 lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); 623 624 if(s1x-s0x<=0 || s1y-s0y<=0) { 625 ppinfo[c][r][nPrec].nblk[2] = 0; 626 ttIncl[c][r][nPrec][2] = new TagTreeDecoder(0,0); 627 ttMaxBP[c][r][nPrec][2] = new TagTreeDecoder(0,0); 628 } else { 629 ttIncl[c][r][nPrec][2] = 630 new TagTreeDecoder(kend-kstart+1,lend-lstart+1); 631 ttMaxBP[c][r][nPrec][2] = 632 new TagTreeDecoder(kend-kstart+1,lend-lstart+1); 633 ppinfo[c][r][nPrec].cblk[2] = 634 new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; 635 ppinfo[c][r][nPrec]. 636 nblk[2] = (kend-kstart+1)*(lend-lstart+1); 637 638 for(int k=kstart; k<=kend; k++) { // Vertical cblks 639 for(int l=lstart; l<=lend; l++) { // Horiz cblks 640 cb = new CBlkCoordInfo(k-k0,l-l0); 641 if(l==l0) { 642 cb.ulx = sb.ulx; 643 } else { 644 cb.ulx = sb.ulx+l*cw-(sb.ulcx-acb0x); 645 } 646 if(k==k0) { 647 cb.uly = sb.uly; 648 } else { 649 cb.uly = sb.uly+k*ch-(sb.ulcy-acb0y); 650 } 651 tmp1 = acb0x+l*cw; 652 tmp1 = (tmp1>sb.ulcx) ? tmp1 : sb.ulcx; 653 tmp2 = acb0x+(l+1)*cw; 654 tmp2 = (tmp2>sb.ulcx+sb.w) ? 655 sb.ulcx+sb.w : tmp2; 656 cb.w = tmp2-tmp1; 657 tmp1 = acb0y+k*ch; 658 tmp1 = (tmp1>sb.ulcy) ? tmp1 : sb.ulcy; 659 tmp2 = acb0y+(k+1)*ch; 660 tmp2 = (tmp2>sb.ulcy+sb.h) ? 661 sb.ulcy+sb.h : tmp2; 662 cb.h = tmp2-tmp1; 663 ppinfo[c][r][nPrec]. 664 cblk[2][k-kstart][l-lstart] = cb; 665 } // Horizontal code-blocks 666 } // Vertical code-blocks 667 } 668 669 // HH subband 670 acb0x = 0; 671 acb0y = 0; 672 673 p0x = acb0x+j*twoppx2; 674 p1x = p0x + twoppx2; 675 p0y = acb0y+i*twoppy2; 676 p1y = p0y + twoppy2; 677 678 sb = (SubbandSyn)root.getSubbandByIdx(r,3); 679 s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x; 680 s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x; 681 s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y; 682 s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y; 683 684 // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch) 685 cw = sb.nomCBlkW; 686 ch = sb.nomCBlkH; 687 k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch); 688 kstart = (int)Math.floor((s0y-acb0y)/(double)ch); 689 kend = (int)Math.floor((s1y-1-acb0y)/(double)ch); 690 l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw); 691 lstart = (int)Math.floor((s0x-acb0x)/(double)cw); 692 lend = (int)Math.floor((s1x-1-acb0x)/(double)cw); 693 694 if(s1x-s0x<=0 || s1y-s0y<=0) { 695 ppinfo[c][r][nPrec].nblk[3] = 0; 696 ttIncl[c][r][nPrec][3] = new TagTreeDecoder(0,0); 697 ttMaxBP[c][r][nPrec][3] = new TagTreeDecoder(0,0); 698 } else { 699 ttIncl[c][r][nPrec][3] = 700 new TagTreeDecoder(kend-kstart+1,lend-lstart+1); 701 ttMaxBP[c][r][nPrec][3] = 702 new TagTreeDecoder(kend-kstart+1,lend-lstart+1); 703 ppinfo[c][r][nPrec].cblk[3] = 704 new CBlkCoordInfo[kend-kstart+1][lend-lstart+1]; 705 ppinfo[c][r][nPrec]. 706 nblk[3] = (kend-kstart+1)*(lend-lstart+1); 707 708 for(int k=kstart; k<=kend; k++) { // Vertical cblks 709 for(int l=lstart; l<=lend; l++) { // Horiz cblks 710 cb = new CBlkCoordInfo(k-k0,l-l0); 711 if(l==l0) { 712 cb.ulx = sb.ulx; 713 } else { 714 cb.ulx = sb.ulx+l*cw-(sb.ulcx-acb0x); 715 } 716 if(k==k0) { 717 cb.uly = sb.uly; 718 } else { 719 cb.uly = sb.uly+k*ch-(sb.ulcy-acb0y); 720 } 721 tmp1 = acb0x+l*cw; 722 tmp1 = (tmp1>sb.ulcx) ? tmp1 : sb.ulcx; 723 tmp2 = acb0x+(l+1)*cw; 724 tmp2 = (tmp2>sb.ulcx+sb.w) ? 725 sb.ulcx+sb.w : tmp2; 726 cb.w = tmp2-tmp1; 727 tmp1 = acb0y+k*ch; 728 tmp1 = (tmp1>sb.ulcy) ? tmp1 : sb.ulcy; 729 tmp2 = acb0y+(k+1)*ch; 730 tmp2 = (tmp2>sb.ulcy+sb.h) ? 731 sb.ulcy+sb.h : tmp2; 732 cb.h = tmp2-tmp1; 733 ppinfo[c][r][nPrec]. 734 cblk[3][k-kstart][l-lstart] = cb; 735 } // Horizontal code-blocks 736 } // Vertical code-blocks 737 } 738 739 } 740 } // Horizontal precincts 741 } // Vertical precincts 742 } 743 744 /** 745 * Gets the number of precincts in a given component and resolution level. 746 * 747 * @param c Component index 748 * 749 * @param r Resolution index 750 * */ 751 public int getNumPrecinct(int c,int r) { 752 return numPrec[c][r].x*numPrec[c][r].y; 753 } 754 755 /** 756 * Read specified packet head and found length of each code-block's piece 757 * of codewords as well as number of skipped most significant bit-planes. 758 * 759 * @param l layer index 760 * 761 * @param r Resolution level index 762 * 763 * @param c Component index 764 * 765 * @param p Precinct index 766 * 767 * @param cbI CBlkInfo array of relevant component and resolution 768 * level. 769 * 770 * @param nb The number of bytes to read in each tile before reaching 771 * output rate (used by truncation mode) 772 * 773 * @return True if specified output rate or EOF is reached. 774 * */ 775 public boolean readPktHead(int l,int r,int c,int p,CBlkInfo[][][] cbI, 776 int[] nb) throws IOException { 777 778 CBlkInfo ccb; 779 int nSeg; // number of segment to read 780 int cbLen; // Length of cblk's code-words 781 int ltp; // last truncation point index 782 int passtype; // coding pass type 783 TagTreeDecoder tdIncl,tdBD; 784 int tmp,tmp2,totnewtp,lblockCur,tpidx; 785 int sumtotnewtp = 0; 786 Point cbc; 787 int startPktHead = ehs.getPos(); 788 if(startPktHead>=ehs.length()) { 789 // EOF reached at the beginning of this packet head 790 return true; 791 } 792 int tIdx = src.getTileIdx(); 793 PktHeaderBitReader bin; 794 int mend,nend; 795 int b; 796 SubbandSyn sb; 797 SubbandSyn root = src.getSynSubbandTree(tIdx,c); 798 799 // If packed packet headers was used, use separate stream for reading 800 // of packet headers 801 if(pph) { 802 bin = new PktHeaderBitReader(pphbais); 803 } else { 804 bin = this.bin; 805 } 806 807 int mins = (r==0) ? 0 : 1; 808 int maxs = (r==0) ? 1 : 4; 809 810 boolean precFound = false; 811 for(int s=mins; s<maxs; s++) { 812 if(p<ppinfo[c][r].length) { 813 precFound = true; 814 } 815 } 816 if(!precFound) { 817 return false; 818 } 819 820 PrecInfo prec = ppinfo[c][r][p]; 821 822 // Synchronize for bit reading 823 bin.sync(); 824 825 // If packet is empty there is no info in it (i.e. no code-blocks) 826 if(bin.readBit()==0) { 827 // No code-block is included 828 cblks = new Vector[maxs+1]; 829 for(int s=mins; s<maxs; s++){ 830 cblks[s] = new Vector(); 831 } 832 pktIdx++; 833 834 // If truncation mode, checks if output rate is reached 835 // unless ncb quit condition is used in which case headers 836 // are not counted 837 if(isTruncMode && maxCB == -1) { 838 tmp = ehs.getPos()-startPktHead; 839 if(tmp>nb[tIdx]) { 840 nb[tIdx] = 0; 841 return true; 842 } else { 843 nb[tIdx] -= tmp; 844 } 845 } 846 847 // Read EPH marker if needed 848 if(ephUsed) { 849 readEPHMarker(bin); 850 } 851 return false; 852 } 853 854 // Packet is not empty => decode info 855 // Loop on each subband in this resolution level 856 if(cblks==null || cblks.length<maxs+1) { 857 cblks = new Vector[maxs+1]; 858 } 859 860 for(int s=mins; s<maxs; s++) { 861 if(cblks[s]==null) { 862 cblks[s] = new Vector(); 863 } else { 864 cblks[s].removeAllElements(); 865 } 866 sb = (SubbandSyn)root.getSubbandByIdx(r,s); 867 // No code-block in this precinct 868 if(prec.nblk[s]==0) { 869 // Go to next subband 870 continue; 871 } 872 873 tdIncl = ttIncl[c][r][p][s]; 874 tdBD = ttMaxBP[c][r][p][s]; 875 876 mend = (prec.cblk[s]==null) ? 0 : prec.cblk[s].length; 877 for(int m=0; m<mend; m++) { // Vertical code-blocks 878 nend = (prec.cblk[s][m]==null) ? 0 : prec.cblk[s][m].length; 879 for (int n=0; n<nend; n++) { // Horizontal code-blocks 880 cbc = prec.cblk[s][m][n].idx; 881 b = cbc.x+cbc.y*sb.numCb.x; 882 883 ccb = cbI[s][cbc.y][cbc.x]; 884 885 try { 886 // If code-block not included in previous layer(s) 887 if(ccb==null || ccb.ctp==0) { 888 if(ccb==null) { 889 ccb = cbI[s][cbc.y][cbc.x] = 890 new CBlkInfo(prec.cblk[s][m][n].ulx, 891 prec.cblk[s][m][n].uly, 892 prec.cblk[s][m][n].w, 893 prec.cblk[s][m][n].h,nl); 894 } 895 ccb.pktIdx[l] = pktIdx; 896 897 // Read inclusion using tag-tree 898 tmp = tdIncl.update(m,n,l+1,bin); 899 if(tmp>l) { // Not included 900 continue; 901 } 902 903 // Read bitdepth using tag-tree 904 tmp = 1;// initialization 905 for(tmp2=1; tmp>=tmp2; tmp2++) { 906 tmp = tdBD.update(m,n,tmp2,bin); 907 } 908 ccb.msbSkipped = tmp2-2; 909 910 // New code-block => at least one truncation point 911 totnewtp = 1; 912 ccb.addNTP(l,0); 913 914 // Check whether ncb quit condition is reached 915 ncb++; 916 if(maxCB != -1 && !ncbQuit && ncb == maxCB){ 917 // ncb quit contidion reached 918 ncbQuit = true; 919 tQuit = tIdx; 920 cQuit = c; 921 sQuit = s; 922 rQuit = r; 923 xQuit = cbc.x; 924 yQuit = cbc.y; 925 } 926 927 } else { // If code-block already included in one of 928 // the previous layers. 929 930 ccb.pktIdx[l] = pktIdx; 931 932 // If not inclused 933 if(bin.readBit()!=1) { 934 continue; 935 } 936 937 // At least 1 more truncation point than 938 // prev. packet 939 totnewtp = 1; 940 } 941 942 // Read new truncation points 943 if(bin.readBit()==1) {// if bit is 1 944 totnewtp++; 945 946 // if next bit is 0 do nothing 947 if(bin.readBit()==1) {//if is 1 948 totnewtp++; 949 950 tmp = bin.readBits(2); 951 totnewtp += tmp; 952 // If next 2 bits are not 11 do nothing 953 if(tmp==0x3) { //if 11 954 tmp = bin.readBits(5); 955 totnewtp += tmp; 956 957 // If next 5 bits are not 11111 do nothing 958 if(tmp==0x1F) { //if 11111 959 totnewtp += bin.readBits(7); 960 } 961 } 962 } 963 } 964 ccb.addNTP(l,totnewtp); 965 sumtotnewtp += totnewtp; 966 cblks[s].addElement(prec.cblk[s][m][n]); 967 968 // Code-block length 969 970 // -- Compute the number of bit to read to obtain 971 // code-block length. 972 // numBits = betaLamda + log2(totnewtp); 973 974 // The length is signalled for each segment in 975 // addition to the final one. The total length is the 976 // sum of all segment lengths. 977 978 // If regular termination in use, then there is one 979 // segment per truncation point present. Otherwise, if 980 // selective arithmetic bypass coding mode is present, 981 // then there is one termination per bypass/MQ and 982 // MQ/bypass transition. Otherwise the only 983 // termination is at the end of the code-block. 984 int options = 985 ((Integer)decSpec.ecopts.getTileCompVal(tIdx,c)). 986 intValue(); 987 988 if( (options&OPT_TERM_PASS) != 0) { 989 // Regular termination in use, one segment per new 990 // pass (i.e. truncation point) 991 nSeg = totnewtp; 992 } else if( (options&OPT_BYPASS) != 0) { 993 // Selective arithmetic coding bypass coding mode 994 // in use, but no regular termination 1 segment up 995 // to the end of the last pass of the 4th most 996 // significant bit-plane, and, in each following 997 // bit-plane, one segment upto the end of the 2nd 998 // pass and one upto the end of the 3rd pass. 999 1000 if(ccb.ctp<=FIRST_BYPASS_PASS_IDX) { 1001 nSeg = 1; 1002 } else { 1003 nSeg = 1; // One at least for last pass 1004 // And one for each other terminated pass 1005 for(tpidx = ccb.ctp-totnewtp; 1006 tpidx < ccb.ctp-1; tpidx++) { 1007 if(tpidx >= FIRST_BYPASS_PASS_IDX-1) { 1008 passtype = 1009 (tpidx+NUM_EMPTY_PASSES_IN_MS_BP)% 1010 NUM_PASSES; 1011 if (passtype==1 || passtype==2) { 1012 // bypass coding just before MQ 1013 // pass or MQ pass just before 1014 // bypass coding => terminated 1015 nSeg++; 1016 } 1017 } 1018 } 1019 } 1020 } else { 1021 // Nothing special in use, just one segment 1022 nSeg = 1; 1023 } 1024 1025 // Reads lblock increment (common to all segments) 1026 while(bin.readBit()!=0) { 1027 lblock[c][r][s][cbc.y][cbc.x]++; 1028 } 1029 1030 if(nSeg==1) { // Only one segment in packet 1031 cbLen = bin.readBits(lblock[c][r][s][cbc.y][cbc.x]+ 1032 MathUtil.log2(totnewtp)); 1033 } else { 1034 // We must read one length per segment 1035 ccb.segLen[l] = new int[nSeg]; 1036 cbLen = 0; 1037 int j; 1038 if((options&OPT_TERM_PASS) != 0) { 1039 // Regular termination: each pass is terminated 1040 for(tpidx=ccb.ctp-totnewtp,j=0; 1041 tpidx<ccb.ctp;tpidx++,j++) { 1042 1043 lblockCur = lblock[c][r][s][cbc.y][cbc.x]; 1044 1045 tmp = bin.readBits(lblockCur); 1046 ccb.segLen[l][j] = tmp; 1047 cbLen += tmp; 1048 } 1049 } else { 1050 // Bypass coding: only some passes are 1051 // terminated 1052 ltp = ccb.ctp-totnewtp-1; 1053 for(tpidx = ccb.ctp-totnewtp, j=0; 1054 tpidx<ccb.ctp-1;tpidx++) { 1055 if(tpidx >= FIRST_BYPASS_PASS_IDX-1) { 1056 passtype = 1057 (tpidx+NUM_EMPTY_PASSES_IN_MS_BP)% 1058 NUM_PASSES; 1059 if (passtype==0) continue; 1060 1061 lblockCur = 1062 lblock[c][r][s][cbc.y][cbc.x]; 1063 tmp = 1064 bin. 1065 readBits(lblockCur+ 1066 MathUtil.log2(tpidx-ltp)); 1067 ccb.segLen[l][j] = tmp; 1068 cbLen += tmp; 1069 ltp = tpidx; 1070 j++; 1071 } 1072 } 1073 // Last pass has always the length sent 1074 lblockCur = lblock[c][r][s][cbc.y][cbc.x]; 1075 tmp = bin.readBits(lblockCur+ 1076 MathUtil.log2(tpidx-ltp)); 1077 cbLen += tmp; 1078 ccb.segLen[l][j] = tmp; 1079 } 1080 } 1081 ccb.len[l] = cbLen; 1082 1083 // If truncation mode, checks if output rate is reached 1084 // unless ncb and lbody quit contitions used. 1085 if(isTruncMode && maxCB==-1) { 1086 tmp = ehs.getPos()-startPktHead; 1087 if(tmp>nb[tIdx]) { 1088 nb[tIdx] = 0; 1089 // Remove found information in this code-block 1090 if(l==0) { 1091 cbI[s][cbc.y][cbc.x] = null; 1092 } else { 1093 ccb.off[l]=ccb.len[l]=0; 1094 ccb.ctp -= ccb.ntp[l]; 1095 ccb.ntp[l] = 0; 1096 ccb.pktIdx[l] = -1; 1097 } 1098 return true; 1099 } 1100 } 1101 1102 } catch(EOFException e) { 1103 // Remove found information in this code-block 1104 if(l==0) { 1105 cbI[s][cbc.y][cbc.x] = null; 1106 } else { 1107 ccb.off[l]=ccb.len[l]=0; 1108 ccb.ctp -= ccb.ntp[l]; 1109 ccb.ntp[l] = 0; 1110 ccb.pktIdx[l] = -1; 1111 } 1112// throw new EOFException(); 1113 return true; 1114 } 1115 } // End loop on horizontal code-blocks 1116 } // End loop on vertical code-blocks 1117 } // End loop on subbands 1118 1119 // Read EPH marker if needed 1120 if(ephUsed) { 1121 readEPHMarker(bin); 1122 } 1123 1124 pktIdx++; 1125 1126 // If truncation mode, checks if output rate is reached 1127 if(isTruncMode && maxCB == -1) { 1128 tmp = ehs.getPos()-startPktHead; 1129 if(tmp>nb[tIdx]) { 1130 nb[tIdx] = 0; 1131 return true; 1132 } else { 1133 nb[tIdx] -= tmp; 1134 } 1135 } 1136 return false; 1137 } 1138 1139 /** 1140 * Reads specificied packet body in order to find offset of each 1141 * code-block's piece of codeword. This use the list of found code-blocks 1142 * in previous red packet head. 1143 * 1144 * @param l layer index 1145 * 1146 * @param r Resolution level index 1147 * 1148 * @param c Component index 1149 * 1150 * @param p Precinct index 1151 * 1152 * @param cbI CBlkInfo array of relevant component and resolution 1153 * level. 1154 * 1155 * @param nb The remainding number of bytes to read from the bit stream in 1156 * each tile before reaching the decoding rate (in truncation mode) 1157 * 1158 * @return True if decoding rate is reached 1159 * */ 1160 public boolean readPktBody(int l,int r,int c,int p,CBlkInfo[][][] cbI, 1161 int[] nb) throws IOException { 1162 int curOff = ehs.getPos(); 1163 Point curCB; 1164 CBlkInfo ccb; 1165 boolean stopRead = false; 1166 int tIdx = src.getTileIdx(); 1167 Point cbc; 1168 1169 boolean precFound = false; 1170 int mins = (r==0) ? 0 : 1; 1171 int maxs = (r==0) ? 1 : 4; 1172 for(int s=mins; s<maxs; s++) { 1173 if(p<ppinfo[c][r].length) { 1174 precFound = true; 1175 } 1176 } 1177 if(!precFound) { 1178 return false; 1179 } 1180 1181 for(int s=mins; s<maxs; s++) { 1182 for(int numCB=0; numCB<cblks[s].size(); numCB++) { 1183 cbc = ((CBlkCoordInfo)cblks[s].elementAt(numCB)).idx; 1184 ccb = cbI[s][cbc.y][cbc.x]; 1185 ccb.off[l] = curOff; 1186 curOff += ccb.len[l]; 1187 try { 1188 ehs.seek(curOff); 1189 } catch(EOFException e) { 1190 if(l==0) { 1191 cbI[s][cbc.y][cbc.x] = null; 1192 } else { 1193 ccb.off[l] = ccb.len[l]=0; 1194 ccb.ctp -= ccb.ntp[l]; 1195 ccb.ntp[l] = 0; 1196 ccb.pktIdx[l] = -1; 1197 } 1198 throw new EOFException(); 1199 } 1200 1201 // If truncation mode 1202 if(isTruncMode) { 1203 if(stopRead || ccb.len[l]>nb[tIdx]) { 1204 // Remove found information in this code-block 1205 if(l==0) { 1206 cbI[s][cbc.y][cbc.x] = null; 1207 } else { 1208 ccb.off[l] = ccb.len[l] = 0; 1209 ccb.ctp -= ccb.ntp[l]; 1210 ccb.ntp[l] = 0; 1211 ccb.pktIdx[l] = -1; 1212 } 1213 stopRead = true; 1214 } 1215 if(!stopRead) { 1216 nb[tIdx] -= ccb.len[l]; 1217 } 1218 } 1219 // If ncb quit condition reached 1220 if(ncbQuit && r == rQuit && s == sQuit && cbc.x == xQuit && 1221 cbc.y == yQuit && tIdx == tQuit && c == cQuit) { 1222 cbI[s][cbc.y][cbc.x] = null; 1223 stopRead = true; 1224 } 1225 } // Loop on code-blocks 1226 } // End loop on subbands 1227 1228 // Seek to the end of the packet 1229 ehs.seek(curOff); 1230 1231 if(stopRead) { 1232 return true; 1233 } else { 1234 return false; 1235 } 1236 } 1237 1238 /** 1239 * Returns the precinct partition width for the specified component, 1240 * resolution level and tile. 1241 * 1242 * @param t the tile index 1243 * 1244 * @param c The index of the component (between 0 and C-1) 1245 * 1246 * @param r The resolution level, from 0 to L. 1247 * 1248 * @return the precinct partition width for the specified component, 1249 * resolution level and tile. 1250 * */ 1251 public final int getPPX(int t,int c,int r){ 1252 return decSpec.pss.getPPX(t,c,r); 1253 } 1254 1255 /** 1256 * Returns the precinct partition height for the specified component, 1257 * resolution level and tile. 1258 * 1259 * @param t the tile index 1260 * 1261 * @param c The index of the component (between 0 and C-1) 1262 * 1263 * @param rl The resolution level, from 0 to L. 1264 * 1265 * @return the precinct partition height in the specified component, for 1266 * the specified resolution level, for the current tile. 1267 * */ 1268 public final int getPPY(int t,int c,int rl) { 1269 return decSpec.pss.getPPY(t,c,rl); 1270 } 1271 1272 /** 1273 * Try to read a SOP marker and check that its sequence number if not out 1274 * of sequence. If so, an error is thrown. 1275 * 1276 * @param nBytes The number of bytes left to read from each tile 1277 * 1278 * @param p Precinct index 1279 * 1280 * @param r Resolution level index 1281 * 1282 * @param c Component index 1283 * */ 1284 public boolean readSOPMarker(int[] nBytes,int p,int c,int r) 1285 throws IOException { 1286 int val; 1287 byte sopArray[] = new byte[6]; 1288 int tIdx = src.getTileIdx(); 1289 int mins = (r==0) ? 0 : 1; 1290 int maxs = (r==0) ? 1 : 4; 1291 boolean precFound = false; 1292 for(int s=mins; s<maxs; s++) { 1293 if(p<ppinfo[c][r].length) { 1294 precFound = true; 1295 } 1296 } 1297 if(!precFound) { 1298 return false; 1299 } 1300 1301 // If SOP markers are not used, return 1302 if(!sopUsed) { 1303 return false; 1304 } 1305 1306 // Check if SOP is used for this packet 1307 int pos = ehs.getPos(); 1308 if( (short)((ehs.read()<<8) | ehs.read()) != Markers.SOP ) { 1309 ehs.seek(pos); 1310 return false; 1311 } 1312 ehs.seek(pos); 1313 1314 // If length of SOP marker greater than remaining bytes to read for 1315 // this tile return true 1316 if(nBytes[tIdx]<6) { 1317 return true; 1318 } 1319 nBytes[tIdx] -= 6; 1320 1321 // Read marker into array 'sopArray' 1322 ehs.readFully(sopArray,0,Markers.SOP_LENGTH); 1323 1324 // Check if this is the correct marker 1325 val = sopArray[0]; 1326 val <<= 8; 1327 val |= sopArray[1]; 1328 if(val!=Markers.SOP) { 1329 throw new Error("Corrupted Bitstream: Could not parse SOP "+ 1330 "marker !"); 1331 } 1332 1333 // Check if length is correct 1334 val = (sopArray[2]&0xff); 1335 val <<= 8; 1336 val |= (sopArray[3]&0xff); 1337 if(val!=4) { 1338 throw new Error("Corrupted Bitstream: Corrupted SOP marker !"); 1339 } 1340 1341 // Check if sequence number if ok 1342 val = (sopArray[4]&0xff); 1343 val <<= 8; 1344 val |= (sopArray[5]&0xff); 1345 1346 if(!pph && val!=pktIdx) { 1347 throw new Error("Corrupted Bitstream: SOP marker out of " 1348 +"sequence !"); 1349 } 1350 if(pph && val!=pktIdx-1) { 1351 // if packed packet headers are used, packet header was read 1352 // before SOP marker segment 1353 throw new Error("Corrupted Bitstream: SOP marker out of " 1354 +"sequence !"); 1355 } 1356 return false; 1357 } 1358 1359 /** 1360 * Try to read an EPH marker. If it is not possible then an Error is 1361 * thrown. 1362 * 1363 * @param bin The packet header reader to read the EPH marker from 1364 * */ 1365 public void readEPHMarker(PktHeaderBitReader bin) throws IOException { 1366 int val; 1367 byte ephArray[] = new byte[2]; 1368 1369 if(bin.usebais) { 1370 bin.bais.read(ephArray,0,Markers.EPH_LENGTH); 1371 } else { 1372 bin.in.readFully(ephArray,0,Markers.EPH_LENGTH); 1373 } 1374 1375 // Check if this is the correct marker 1376 val = ephArray[0]; 1377 val <<= 8; 1378 val |= ephArray[1]; 1379 if (val!=Markers.EPH) { 1380 throw new Error("Corrupted Bitstream: Could not parse EPH " 1381 +"marker ! "); 1382 } 1383 } 1384 1385 /** 1386 * Get PrecInfo instance of the specified resolution level, component and 1387 * precinct. 1388 * 1389 * @param c Component index. 1390 * 1391 * @param r Resolution level index. 1392 * 1393 * @param p Precinct index. 1394 * */ 1395 public PrecInfo getPrecInfo(int c,int r,int p) { 1396 return ppinfo[c][r][p]; 1397 } 1398 1399}