0001: /*
0002: * $RCSfile: PktDecoder.java,v $
0003: * $Revision: 1.1 $
0004: * $Date: 2005/02/11 05:02:01 $
0005: * $State: Exp $
0006: *
0007: * Class: PktDecoder
0008: *
0009: * Description: Reads packets heads and keeps location of
0010: * code-blocks' codewords
0011: *
0012: *
0013: *
0014: * COPYRIGHT:
0015: *
0016: * This software module was originally developed by Raphaël Grosbois and
0017: * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
0018: * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
0019: * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
0020: * Centre France S.A) in the course of development of the JPEG2000
0021: * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
0022: * software module is an implementation of a part of the JPEG 2000
0023: * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
0024: * Systems AB and Canon Research Centre France S.A (collectively JJ2000
0025: * Partners) agree not to assert against ISO/IEC and users of the JPEG
0026: * 2000 Standard (Users) any of their rights under the copyright, not
0027: * including other intellectual property rights, for this software module
0028: * with respect to the usage by ISO/IEC and Users of this software module
0029: * or modifications thereof for use in hardware or software products
0030: * claiming conformance to the JPEG 2000 Standard. Those intending to use
0031: * this software module in hardware or software products are advised that
0032: * their use may infringe existing patents. The original developers of
0033: * this software module, JJ2000 Partners and ISO/IEC assume no liability
0034: * for use of this software module or modifications thereof. No license
0035: * or right to this software module is granted for non JPEG 2000 Standard
0036: * conforming products. JJ2000 Partners have full right to use this
0037: * software module for his/her own purpose, assign or donate this
0038: * software module to any third party and to inhibit third parties from
0039: * using this software module for non JPEG 2000 Standard conforming
0040: * products. This copyright notice must be included in all copies or
0041: * derivative works of this software module.
0042: *
0043: * Copyright (c) 1999/2000 JJ2000 Partners.
0044: * */
0045: package jj2000.j2k.codestream.reader;
0046:
0047: import java.awt.Point;
0048:
0049: import jj2000.j2k.wavelet.synthesis.*;
0050: import jj2000.j2k.codestream.*;
0051: import jj2000.j2k.entropy.*;
0052: import jj2000.j2k.wavelet.*;
0053: import jj2000.j2k.decoder.*;
0054: import jj2000.j2k.image.*;
0055: import jj2000.j2k.util.*;
0056: import jj2000.j2k.io.*;
0057:
0058: import java.util.*;
0059: import java.io.*;
0060:
0061: /**
0062: * This class is used to read packet's head and body. All the members must be
0063: * re-initialized at the beginning of each tile thanks to the restart()
0064: * method.
0065: * */
0066: public class PktDecoder implements StdEntropyCoderOptions {
0067:
0068: /** Reference to the codestream reader agent */
0069: private BitstreamReaderAgent src;
0070:
0071: /** Flag indicating whether packed packet header was used for this tile*/
0072: private boolean pph = false;
0073:
0074: /** The packed packet header if it was used */
0075: private ByteArrayInputStream pphbais;
0076:
0077: /** Reference to decoder specifications */
0078: private DecoderSpecs decSpec;
0079:
0080: /** Reference to the HeaderDecoder */
0081: private HeaderDecoder hd;
0082:
0083: /** Initial value of the state variable associated with code-block
0084: * length. */
0085: private final int INIT_LBLOCK = 3;
0086:
0087: /** The wrapper to read bits for the packet heads */
0088: private PktHeaderBitReader bin;
0089:
0090: /** Reference to the stream where to read from */
0091: private RandomAccessIO ehs;
0092:
0093: /**
0094: * Maximum number of precincts :
0095: *
0096: * <ul>
0097: * <li> 1st dim: component index.</li>
0098: * <li> 2nd dim: resolution level index.</li>
0099: * </ul>
0100: * */
0101: private Point[][] numPrec;
0102:
0103: /** Index of the current tile */
0104: private int tIdx;
0105:
0106: /**
0107: * Array containing the coordinates, width, height, indexes, ... of the
0108: * precincts in the current tile:
0109: *
0110: * <ul>
0111: * <li> 1st dim: component index.</li>
0112: * <li> 2nd dim: resolution level index.</li>
0113: * <li> 3rd dim: precinct index.</li>
0114: * </ul>
0115: * */
0116: private PrecInfo[][][] ppinfo;
0117:
0118: /**
0119: * Lblock value used to read code size information in each packet head:
0120: *
0121: * <ul>
0122: * <li> 1st dim: component index.</li>
0123: * <li> 2nd dim: resolution level index.</li>
0124: * <li> 3rd dim: subband index.</li>
0125: * <li> 4th/5th dim: code-block index (vert. and horiz.).</li>
0126: * </ul>
0127: * */
0128: private int[][][][][] lblock;
0129:
0130: /**
0131: * Tag tree used to read inclusion informations in packet's head:
0132: *
0133: * <ul>
0134: * <li> 1st dim: component index.</li>
0135: * <li> 2nd dim: resolution level index.</li>
0136: * <li> 3rd dim: precinct index.</li>
0137: * <li> 4th dim: subband index.</li>
0138: * */
0139: private TagTreeDecoder[][][][] ttIncl;
0140:
0141: /**
0142: * Tag tree used to read bit-depth information in packet's head:
0143: *
0144: * <ul>
0145: * <li> 1st dim: component index.</li>
0146: * <li> 2nd dim: resolution level index.</li>
0147: * <li> 3rd dim: precinct index.</li>
0148: * <li> 4th dim: subband index.</li>
0149: * </ul>
0150: * */
0151: private TagTreeDecoder[][][][] ttMaxBP;
0152:
0153: /** Number of layers in t he current tile */
0154: private int nl = 0;
0155:
0156: /** The number of components */
0157: private int nc;
0158:
0159: /** Whether or not SOP marker segment are used */
0160: private boolean sopUsed = false;
0161:
0162: /** Whether or not EPH marker are used */
0163: private boolean ephUsed = false;
0164:
0165: /** Index of the current packet in the tile. Used with SOP marker
0166: segment*/
0167: private int pktIdx;
0168:
0169: /** List of code-blocks found in last read packet head (one list
0170: * per subband) */
0171: private Vector[] cblks;
0172:
0173: /** Number of codeblocks encountered. used for ncb quit condition*/
0174: private int ncb;
0175:
0176: /** Maximum number of codeblocks to read before ncb quit condition is
0177: * reached */
0178: private int maxCB;
0179:
0180: /** Flag indicating whether ncb quit condition has been reached */
0181: private boolean ncbQuit;
0182:
0183: /** The tile in which the ncb quit condition was reached */
0184: private int tQuit;
0185:
0186: /** The component in which the ncb quit condition was reached */
0187: private int cQuit;
0188:
0189: /** The subband in which the ncb quit condition was reached */
0190: private int sQuit;
0191:
0192: /** The resolution in which the ncb quit condition was reached */
0193: private int rQuit;
0194:
0195: /** The x position of the last code block before ncb quit reached */
0196: private int xQuit;
0197:
0198: /** The y position of the last code block before ncb quit reached */
0199: private int yQuit;
0200:
0201: /** True if truncation mode is used. False if it is parsing mode */
0202: private boolean isTruncMode;
0203:
0204: /**
0205: * Creates an empty PktDecoder object associated with given decoder
0206: * specifications and HeaderDecoder. This object must be initialized
0207: * thanks to the restart method before being used.
0208: *
0209: * @param decSpec The decoder specifications.
0210: *
0211: * @param hd The HeaderDecoder instance.
0212: *
0213: * @param ehs The stream where to read data from.
0214: *
0215: * @param src The bit stream reader agent.
0216: *
0217: * @param isTruncMode Whether or not truncation mode is required.
0218: *
0219: * @param maxCB The maximum number of code-blocks to read before ncbquit
0220: *
0221: * */
0222: public PktDecoder(DecoderSpecs decSpec, HeaderDecoder hd,
0223: RandomAccessIO ehs, BitstreamReaderAgent src,
0224: boolean isTruncMode, int maxCB) {
0225: this .decSpec = decSpec;
0226: this .hd = hd;
0227: this .ehs = ehs;
0228: this .isTruncMode = isTruncMode;
0229: bin = new PktHeaderBitReader(ehs);
0230: this .src = src;
0231: ncb = 0;
0232: ncbQuit = false;
0233: this .maxCB = maxCB;
0234: }
0235:
0236: /**
0237: * Re-initialize the PktDecoder instance at the beginning of a new tile.
0238: *
0239: * @param nc The number of components in this tile
0240: *
0241: * @param mdl The maximum number of decomposition level in each component
0242: * of this tile
0243: *
0244: * @param nl The number of layers in this tile
0245: *
0246: * @param cbI The code-blocks array
0247: *
0248: * @param pph Flag indicating whether packed packet headers was used
0249: *
0250: * @param pphbais Stream containing the packed packet headers
0251: * */
0252: public CBlkInfo[][][][][] restart(int nc, int[] mdl, int nl,
0253: CBlkInfo[][][][][] cbI, boolean pph,
0254: ByteArrayInputStream pphbais) {
0255: this .nc = nc;
0256: this .nl = nl;
0257: this .tIdx = src.getTileIdx();
0258: this .pph = pph;
0259: this .pphbais = pphbais;
0260:
0261: sopUsed = ((Boolean) decSpec.sops.getTileDef(tIdx))
0262: .booleanValue();
0263: pktIdx = 0;
0264: ephUsed = ((Boolean) decSpec.ephs.getTileDef(tIdx))
0265: .booleanValue();
0266:
0267: cbI = new CBlkInfo[nc][][][][];
0268: lblock = new int[nc][][][][];
0269: ttIncl = new TagTreeDecoder[nc][][][];
0270: ttMaxBP = new TagTreeDecoder[nc][][][];
0271: numPrec = new Point[nc][];
0272: ppinfo = new PrecInfo[nc][][];
0273:
0274: // Used to compute the maximum number of precincts for each resolution
0275: // level
0276: int tcx0, tcy0, tcx1, tcy1; // Current tile position in the domain of
0277: // the image component
0278: int trx0, try0, trx1, try1; // Current tile position in the reduced
0279: // resolution image domain
0280: int xrsiz, yrsiz; // Component sub-sampling factors
0281:
0282: SubbandSyn root, sb;
0283: int mins, maxs;
0284: Point nBlk = null;
0285: int cb0x = src.getCbULX();
0286: int cb0y = src.getCbULY();
0287:
0288: for (int c = 0; c < nc; c++) {
0289: cbI[c] = new CBlkInfo[mdl[c] + 1][][][];
0290: lblock[c] = new int[mdl[c] + 1][][][];
0291: ttIncl[c] = new TagTreeDecoder[mdl[c] + 1][][];
0292: ttMaxBP[c] = new TagTreeDecoder[mdl[c] + 1][][];
0293: numPrec[c] = new Point[mdl[c] + 1];
0294: ppinfo[c] = new PrecInfo[mdl[c] + 1][];
0295:
0296: // Get the tile-component coordinates on the reference grid
0297: tcx0 = src.getResULX(c, mdl[c]);
0298: tcy0 = src.getResULY(c, mdl[c]);
0299: tcx1 = tcx0 + src.getTileCompWidth(tIdx, c, mdl[c]);
0300: tcy1 = tcy0 + src.getTileCompHeight(tIdx, c, mdl[c]);
0301:
0302: for (int r = 0; r <= mdl[c]; r++) {
0303:
0304: // Tile's coordinates in the reduced resolution image domain
0305: trx0 = (int) Math.ceil(tcx0
0306: / (double) (1 << (mdl[c] - r)));
0307: try0 = (int) Math.ceil(tcy0
0308: / (double) (1 << (mdl[c] - r)));
0309: trx1 = (int) Math.ceil(tcx1
0310: / (double) (1 << (mdl[c] - r)));
0311: try1 = (int) Math.ceil(tcy1
0312: / (double) (1 << (mdl[c] - r)));
0313:
0314: // Calculate the maximum number of precincts for each
0315: // resolution level taking into account tile specific options.
0316: double twoppx = (double) getPPX(tIdx, c, r);
0317: double twoppy = (double) getPPY(tIdx, c, r);
0318: numPrec[c][r] = new Point();
0319: if (trx1 > trx0) {
0320: numPrec[c][r].x = (int) Math.ceil((trx1 - cb0x)
0321: / twoppx)
0322: - (int) Math.floor((trx0 - cb0x) / twoppx);
0323: } else {
0324: numPrec[c][r].x = 0;
0325: }
0326: if (try1 > try0) {
0327: numPrec[c][r].y = (int) Math.ceil((try1 - cb0y)
0328: / twoppy)
0329: - (int) Math.floor((try0 - cb0y) / twoppy);
0330: } else {
0331: numPrec[c][r].y = 0;
0332: }
0333:
0334: // First and last subbands indexes
0335: mins = (r == 0) ? 0 : 1;
0336: maxs = (r == 0) ? 1 : 4;
0337:
0338: int maxPrec = numPrec[c][r].x * numPrec[c][r].y;
0339:
0340: ttIncl[c][r] = new TagTreeDecoder[maxPrec][maxs + 1];
0341: ttMaxBP[c][r] = new TagTreeDecoder[maxPrec][maxs + 1];
0342: cbI[c][r] = new CBlkInfo[maxs + 1][][];
0343: lblock[c][r] = new int[maxs + 1][][];
0344:
0345: ppinfo[c][r] = new PrecInfo[maxPrec];
0346: fillPrecInfo(c, r, mdl[c]);
0347:
0348: root = (SubbandSyn) src.getSynSubbandTree(tIdx, c);
0349: for (int s = mins; s < maxs; s++) {
0350: sb = (SubbandSyn) root.getSubbandByIdx(r, s);
0351: nBlk = sb.numCb;
0352:
0353: cbI[c][r][s] = new CBlkInfo[nBlk.y][nBlk.x];
0354: lblock[c][r][s] = new int[nBlk.y][nBlk.x];
0355:
0356: for (int i = nBlk.y - 1; i >= 0; i--) {
0357: ArrayUtil.intArraySet(lblock[c][r][s][i],
0358: INIT_LBLOCK);
0359: }
0360: } // loop on subbands
0361: } // End loop on resolution levels
0362: } // End loop on components
0363:
0364: return cbI;
0365: }
0366:
0367: /**
0368: * Retrives precincts and code-blocks coordinates in the given resolution,
0369: * level and component. Finishes TagTreeEncoder initialization as well.
0370: *
0371: * @param c Component index.
0372: *
0373: * @param r Resolution level index.
0374: *
0375: * @param mdl Number of decomposition level in component <tt>c</tt>.
0376: * */
0377: private void fillPrecInfo(int c, int r, int mdl) {
0378: if (ppinfo[c][r].length == 0)
0379: return; // No precinct in this
0380: // resolution level
0381:
0382: Point tileI = src.getTile(null);
0383: Point nTiles = src.getNumTiles(null);
0384:
0385: int xsiz, ysiz, x0siz, y0siz;
0386: int xt0siz, yt0siz;
0387: int xtsiz, ytsiz;
0388:
0389: xt0siz = src.getTilePartULX();
0390: yt0siz = src.getTilePartULY();
0391: xtsiz = src.getNomTileWidth();
0392: ytsiz = src.getNomTileHeight();
0393: x0siz = hd.getImgULX();
0394: y0siz = hd.getImgULY();
0395: xsiz = hd.getImgWidth();
0396: ysiz = hd.getImgHeight();
0397:
0398: int tx0 = (tileI.x == 0) ? x0siz : xt0siz + tileI.x * xtsiz;
0399: int ty0 = (tileI.y == 0) ? y0siz : yt0siz + tileI.y * ytsiz;
0400: int tx1 = (tileI.x != nTiles.x - 1) ? xt0siz + (tileI.x + 1)
0401: * xtsiz : xsiz;
0402: int ty1 = (tileI.y != nTiles.y - 1) ? yt0siz + (tileI.y + 1)
0403: * ytsiz : ysiz;
0404:
0405: int xrsiz = hd.getCompSubsX(c);
0406: int yrsiz = hd.getCompSubsY(c);
0407:
0408: int tcx0 = src.getResULX(c, mdl);
0409: int tcy0 = src.getResULY(c, mdl);
0410: int tcx1 = tcx0 + src.getTileCompWidth(tIdx, c, mdl);
0411: int tcy1 = tcy0 + src.getTileCompHeight(tIdx, c, mdl);
0412:
0413: int ndl = mdl - r;
0414: int trx0 = (int) Math.ceil(tcx0 / (double) (1 << ndl));
0415: int try0 = (int) Math.ceil(tcy0 / (double) (1 << ndl));
0416: int trx1 = (int) Math.ceil(tcx1 / (double) (1 << ndl));
0417: int try1 = (int) Math.ceil(tcy1 / (double) (1 << ndl));
0418:
0419: int cb0x = src.getCbULX();
0420: int cb0y = src.getCbULY();
0421:
0422: double twoppx = (double) getPPX(tIdx, c, r);
0423: double twoppy = (double) getPPY(tIdx, c, r);
0424: int twoppx2 = (int) (twoppx / 2);
0425: int twoppy2 = (int) (twoppy / 2);
0426:
0427: // Precincts are located at (cb0x+i*twoppx,cb0y+j*twoppy)
0428: // Valid precincts are those which intersect with the current
0429: // resolution level
0430: int maxPrec = ppinfo[c][r].length;
0431: int nPrec = 0;
0432:
0433: int istart = (int) Math.floor((try0 - cb0y) / twoppy);
0434: int iend = (int) Math.floor((try1 - 1 - cb0y) / twoppy);
0435: int jstart = (int) Math.floor((trx0 - cb0x) / twoppx);
0436: int jend = (int) Math.floor((trx1 - 1 - cb0x) / twoppx);
0437:
0438: int acb0x, acb0y;
0439:
0440: SubbandSyn root = src.getSynSubbandTree(tIdx, c);
0441: SubbandSyn sb = null;
0442:
0443: int p0x, p0y, p1x, p1y; // Precinct projection in subband
0444: int s0x, s0y, s1x, s1y; // Active subband portion
0445: int cw, ch;
0446: int kstart, kend, lstart, lend, k0, l0;
0447: int prg_ulx, prg_uly;
0448: int prg_w = (int) twoppx << ndl;
0449: int prg_h = (int) twoppy << ndl;
0450: int tmp1, tmp2;
0451:
0452: CBlkCoordInfo cb;
0453:
0454: for (int i = istart; i <= iend; i++) { // Vertical precincts
0455: for (int j = jstart; j <= jend; j++, nPrec++) { // Horizontal precincts
0456: if (j == jstart
0457: && (trx0 - cb0x) % (xrsiz * ((int) twoppx)) != 0) {
0458: prg_ulx = tx0;
0459: } else {
0460: prg_ulx = cb0x + j * xrsiz * ((int) twoppx << ndl);
0461: }
0462: if (i == istart
0463: && (try0 - cb0y) % (yrsiz * ((int) twoppy)) != 0) {
0464: prg_uly = ty0;
0465: } else {
0466: prg_uly = cb0y + i * yrsiz * ((int) twoppy << ndl);
0467: }
0468:
0469: ppinfo[c][r][nPrec] = new PrecInfo(r, (int) (cb0x + j
0470: * twoppx), (int) (cb0y + i * twoppy),
0471: (int) twoppx, (int) twoppy, prg_ulx, prg_uly,
0472: prg_w, prg_h);
0473:
0474: if (r == 0) { // LL subband
0475: acb0x = cb0x;
0476: acb0y = cb0y;
0477:
0478: p0x = acb0x + j * (int) twoppx;
0479: p1x = p0x + (int) twoppx;
0480: p0y = acb0y + i * (int) twoppy;
0481: p1y = p0y + (int) twoppy;
0482:
0483: sb = (SubbandSyn) root.getSubbandByIdx(0, 0);
0484: s0x = (p0x < sb.ulcx) ? sb.ulcx : p0x;
0485: s1x = (p1x > sb.ulcx + sb.w) ? sb.ulcx + sb.w : p1x;
0486: s0y = (p0y < sb.ulcy) ? sb.ulcy : p0y;
0487: s1y = (p1y > sb.ulcy + sb.h) ? sb.ulcy + sb.h : p1y;
0488:
0489: // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
0490: cw = sb.nomCBlkW;
0491: ch = sb.nomCBlkH;
0492: k0 = (int) Math.floor((sb.ulcy - acb0y)
0493: / (double) ch);
0494: kstart = (int) Math.floor((s0y - acb0y)
0495: / (double) ch);
0496: kend = (int) Math.floor((s1y - 1 - acb0y)
0497: / (double) ch);
0498: l0 = (int) Math.floor((sb.ulcx - acb0x)
0499: / (double) cw);
0500: lstart = (int) Math.floor((s0x - acb0x)
0501: / (double) cw);
0502: lend = (int) Math.floor((s1x - 1 - acb0x)
0503: / (double) cw);
0504:
0505: if (s1x - s0x <= 0 || s1y - s0y <= 0) {
0506: ppinfo[c][r][nPrec].nblk[0] = 0;
0507: ttIncl[c][r][nPrec][0] = new TagTreeDecoder(0,
0508: 0);
0509: ttMaxBP[c][r][nPrec][0] = new TagTreeDecoder(0,
0510: 0);
0511: } else {
0512: ttIncl[c][r][nPrec][0] = new TagTreeDecoder(
0513: kend - kstart + 1, lend - lstart + 1);
0514: ttMaxBP[c][r][nPrec][0] = new TagTreeDecoder(
0515: kend - kstart + 1, lend - lstart + 1);
0516: ppinfo[c][r][nPrec].cblk[0] = new CBlkCoordInfo[kend
0517: - kstart + 1][lend - lstart + 1];
0518: ppinfo[c][r][nPrec].nblk[0] = (kend - kstart + 1)
0519: * (lend - lstart + 1);
0520:
0521: for (int k = kstart; k <= kend; k++) { // Vertical cblks
0522: for (int l = lstart; l <= lend; l++) { // Horiz. cblks
0523: cb = new CBlkCoordInfo(k - k0, l - l0);
0524: if (l == l0) {
0525: cb.ulx = sb.ulx;
0526: } else {
0527: cb.ulx = sb.ulx + l * cw
0528: - (sb.ulcx - acb0x);
0529: }
0530: if (k == k0) {
0531: cb.uly = sb.uly;
0532: } else {
0533: cb.uly = sb.uly + k * ch
0534: - (sb.ulcy - acb0y);
0535: }
0536: tmp1 = acb0x + l * cw;
0537: tmp1 = (tmp1 > sb.ulcx) ? tmp1
0538: : sb.ulcx;
0539: tmp2 = acb0x + (l + 1) * cw;
0540: tmp2 = (tmp2 > sb.ulcx + sb.w) ? sb.ulcx
0541: + sb.w
0542: : tmp2;
0543: cb.w = tmp2 - tmp1;
0544: tmp1 = acb0y + k * ch;
0545: tmp1 = (tmp1 > sb.ulcy) ? tmp1
0546: : sb.ulcy;
0547: tmp2 = acb0y + (k + 1) * ch;
0548: tmp2 = (tmp2 > sb.ulcy + sb.h) ? sb.ulcy
0549: + sb.h
0550: : tmp2;
0551: cb.h = tmp2 - tmp1;
0552: ppinfo[c][r][nPrec].cblk[0][k - kstart][l
0553: - lstart] = cb;
0554: } // Horizontal code-blocks
0555: } // Vertical code-blocks
0556: }
0557: } else { // HL, LH and HH subbands
0558: // HL subband
0559: acb0x = 0;
0560: acb0y = cb0y;
0561:
0562: p0x = acb0x + j * twoppx2;
0563: p1x = p0x + twoppx2;
0564: p0y = acb0y + i * twoppy2;
0565: p1y = p0y + twoppy2;
0566:
0567: sb = (SubbandSyn) root.getSubbandByIdx(r, 1);
0568: s0x = (p0x < sb.ulcx) ? sb.ulcx : p0x;
0569: s1x = (p1x > sb.ulcx + sb.w) ? sb.ulcx + sb.w : p1x;
0570: s0y = (p0y < sb.ulcy) ? sb.ulcy : p0y;
0571: s1y = (p1y > sb.ulcy + sb.h) ? sb.ulcy + sb.h : p1y;
0572:
0573: // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
0574: cw = sb.nomCBlkW;
0575: ch = sb.nomCBlkH;
0576: k0 = (int) Math.floor((sb.ulcy - acb0y)
0577: / (double) ch);
0578: kstart = (int) Math.floor((s0y - acb0y)
0579: / (double) ch);
0580: kend = (int) Math.floor((s1y - 1 - acb0y)
0581: / (double) ch);
0582: l0 = (int) Math.floor((sb.ulcx - acb0x)
0583: / (double) cw);
0584: lstart = (int) Math.floor((s0x - acb0x)
0585: / (double) cw);
0586: lend = (int) Math.floor((s1x - 1 - acb0x)
0587: / (double) cw);
0588:
0589: if (s1x - s0x <= 0 || s1y - s0y <= 0) {
0590: ppinfo[c][r][nPrec].nblk[1] = 0;
0591: ttIncl[c][r][nPrec][1] = new TagTreeDecoder(0,
0592: 0);
0593: ttMaxBP[c][r][nPrec][1] = new TagTreeDecoder(0,
0594: 0);
0595: } else {
0596: ttIncl[c][r][nPrec][1] = new TagTreeDecoder(
0597: kend - kstart + 1, lend - lstart + 1);
0598: ttMaxBP[c][r][nPrec][1] = new TagTreeDecoder(
0599: kend - kstart + 1, lend - lstart + 1);
0600: ppinfo[c][r][nPrec].cblk[1] = new CBlkCoordInfo[kend
0601: - kstart + 1][lend - lstart + 1];
0602: ppinfo[c][r][nPrec].nblk[1] = (kend - kstart + 1)
0603: * (lend - lstart + 1);
0604:
0605: for (int k = kstart; k <= kend; k++) { // Vertical cblks
0606: for (int l = lstart; l <= lend; l++) { // Horiz. cblks
0607: cb = new CBlkCoordInfo(k - k0, l - l0);
0608: if (l == l0) {
0609: cb.ulx = sb.ulx;
0610: } else {
0611: cb.ulx = sb.ulx + l * cw
0612: - (sb.ulcx - acb0x);
0613: }
0614: if (k == k0) {
0615: cb.uly = sb.uly;
0616: } else {
0617: cb.uly = sb.uly + k * ch
0618: - (sb.ulcy - acb0y);
0619: }
0620: tmp1 = acb0x + l * cw;
0621: tmp1 = (tmp1 > sb.ulcx) ? tmp1
0622: : sb.ulcx;
0623: tmp2 = acb0x + (l + 1) * cw;
0624: tmp2 = (tmp2 > sb.ulcx + sb.w) ? sb.ulcx
0625: + sb.w
0626: : tmp2;
0627: cb.w = tmp2 - tmp1;
0628: tmp1 = acb0y + k * ch;
0629: tmp1 = (tmp1 > sb.ulcy) ? tmp1
0630: : sb.ulcy;
0631: tmp2 = acb0y + (k + 1) * ch;
0632: tmp2 = (tmp2 > sb.ulcy + sb.h) ? sb.ulcy
0633: + sb.h
0634: : tmp2;
0635: cb.h = tmp2 - tmp1;
0636: ppinfo[c][r][nPrec].cblk[1][k - kstart][l
0637: - lstart] = cb;
0638: } // Horizontal code-blocks
0639: } // Vertical code-blocks
0640: }
0641:
0642: // LH subband
0643: acb0x = cb0x;
0644: acb0y = 0;
0645:
0646: p0x = acb0x + j * twoppx2;
0647: p1x = p0x + twoppx2;
0648: p0y = acb0y + i * twoppy2;
0649: p1y = p0y + twoppy2;
0650:
0651: sb = (SubbandSyn) root.getSubbandByIdx(r, 2);
0652: s0x = (p0x < sb.ulcx) ? sb.ulcx : p0x;
0653: s1x = (p1x > sb.ulcx + sb.w) ? sb.ulcx + sb.w : p1x;
0654: s0y = (p0y < sb.ulcy) ? sb.ulcy : p0y;
0655: s1y = (p1y > sb.ulcy + sb.h) ? sb.ulcy + sb.h : p1y;
0656:
0657: // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
0658: cw = sb.nomCBlkW;
0659: ch = sb.nomCBlkH;
0660: k0 = (int) Math.floor((sb.ulcy - acb0y)
0661: / (double) ch);
0662: kstart = (int) Math.floor((s0y - acb0y)
0663: / (double) ch);
0664: kend = (int) Math.floor((s1y - 1 - acb0y)
0665: / (double) ch);
0666: l0 = (int) Math.floor((sb.ulcx - acb0x)
0667: / (double) cw);
0668: lstart = (int) Math.floor((s0x - acb0x)
0669: / (double) cw);
0670: lend = (int) Math.floor((s1x - 1 - acb0x)
0671: / (double) cw);
0672:
0673: if (s1x - s0x <= 0 || s1y - s0y <= 0) {
0674: ppinfo[c][r][nPrec].nblk[2] = 0;
0675: ttIncl[c][r][nPrec][2] = new TagTreeDecoder(0,
0676: 0);
0677: ttMaxBP[c][r][nPrec][2] = new TagTreeDecoder(0,
0678: 0);
0679: } else {
0680: ttIncl[c][r][nPrec][2] = new TagTreeDecoder(
0681: kend - kstart + 1, lend - lstart + 1);
0682: ttMaxBP[c][r][nPrec][2] = new TagTreeDecoder(
0683: kend - kstart + 1, lend - lstart + 1);
0684: ppinfo[c][r][nPrec].cblk[2] = new CBlkCoordInfo[kend
0685: - kstart + 1][lend - lstart + 1];
0686: ppinfo[c][r][nPrec].nblk[2] = (kend - kstart + 1)
0687: * (lend - lstart + 1);
0688:
0689: for (int k = kstart; k <= kend; k++) { // Vertical cblks
0690: for (int l = lstart; l <= lend; l++) { // Horiz cblks
0691: cb = new CBlkCoordInfo(k - k0, l - l0);
0692: if (l == l0) {
0693: cb.ulx = sb.ulx;
0694: } else {
0695: cb.ulx = sb.ulx + l * cw
0696: - (sb.ulcx - acb0x);
0697: }
0698: if (k == k0) {
0699: cb.uly = sb.uly;
0700: } else {
0701: cb.uly = sb.uly + k * ch
0702: - (sb.ulcy - acb0y);
0703: }
0704: tmp1 = acb0x + l * cw;
0705: tmp1 = (tmp1 > sb.ulcx) ? tmp1
0706: : sb.ulcx;
0707: tmp2 = acb0x + (l + 1) * cw;
0708: tmp2 = (tmp2 > sb.ulcx + sb.w) ? sb.ulcx
0709: + sb.w
0710: : tmp2;
0711: cb.w = tmp2 - tmp1;
0712: tmp1 = acb0y + k * ch;
0713: tmp1 = (tmp1 > sb.ulcy) ? tmp1
0714: : sb.ulcy;
0715: tmp2 = acb0y + (k + 1) * ch;
0716: tmp2 = (tmp2 > sb.ulcy + sb.h) ? sb.ulcy
0717: + sb.h
0718: : tmp2;
0719: cb.h = tmp2 - tmp1;
0720: ppinfo[c][r][nPrec].cblk[2][k - kstart][l
0721: - lstart] = cb;
0722: } // Horizontal code-blocks
0723: } // Vertical code-blocks
0724: }
0725:
0726: // HH subband
0727: acb0x = 0;
0728: acb0y = 0;
0729:
0730: p0x = acb0x + j * twoppx2;
0731: p1x = p0x + twoppx2;
0732: p0y = acb0y + i * twoppy2;
0733: p1y = p0y + twoppy2;
0734:
0735: sb = (SubbandSyn) root.getSubbandByIdx(r, 3);
0736: s0x = (p0x < sb.ulcx) ? sb.ulcx : p0x;
0737: s1x = (p1x > sb.ulcx + sb.w) ? sb.ulcx + sb.w : p1x;
0738: s0y = (p0y < sb.ulcy) ? sb.ulcy : p0y;
0739: s1y = (p1y > sb.ulcy + sb.h) ? sb.ulcy + sb.h : p1y;
0740:
0741: // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
0742: cw = sb.nomCBlkW;
0743: ch = sb.nomCBlkH;
0744: k0 = (int) Math.floor((sb.ulcy - acb0y)
0745: / (double) ch);
0746: kstart = (int) Math.floor((s0y - acb0y)
0747: / (double) ch);
0748: kend = (int) Math.floor((s1y - 1 - acb0y)
0749: / (double) ch);
0750: l0 = (int) Math.floor((sb.ulcx - acb0x)
0751: / (double) cw);
0752: lstart = (int) Math.floor((s0x - acb0x)
0753: / (double) cw);
0754: lend = (int) Math.floor((s1x - 1 - acb0x)
0755: / (double) cw);
0756:
0757: if (s1x - s0x <= 0 || s1y - s0y <= 0) {
0758: ppinfo[c][r][nPrec].nblk[3] = 0;
0759: ttIncl[c][r][nPrec][3] = new TagTreeDecoder(0,
0760: 0);
0761: ttMaxBP[c][r][nPrec][3] = new TagTreeDecoder(0,
0762: 0);
0763: } else {
0764: ttIncl[c][r][nPrec][3] = new TagTreeDecoder(
0765: kend - kstart + 1, lend - lstart + 1);
0766: ttMaxBP[c][r][nPrec][3] = new TagTreeDecoder(
0767: kend - kstart + 1, lend - lstart + 1);
0768: ppinfo[c][r][nPrec].cblk[3] = new CBlkCoordInfo[kend
0769: - kstart + 1][lend - lstart + 1];
0770: ppinfo[c][r][nPrec].nblk[3] = (kend - kstart + 1)
0771: * (lend - lstart + 1);
0772:
0773: for (int k = kstart; k <= kend; k++) { // Vertical cblks
0774: for (int l = lstart; l <= lend; l++) { // Horiz cblks
0775: cb = new CBlkCoordInfo(k - k0, l - l0);
0776: if (l == l0) {
0777: cb.ulx = sb.ulx;
0778: } else {
0779: cb.ulx = sb.ulx + l * cw
0780: - (sb.ulcx - acb0x);
0781: }
0782: if (k == k0) {
0783: cb.uly = sb.uly;
0784: } else {
0785: cb.uly = sb.uly + k * ch
0786: - (sb.ulcy - acb0y);
0787: }
0788: tmp1 = acb0x + l * cw;
0789: tmp1 = (tmp1 > sb.ulcx) ? tmp1
0790: : sb.ulcx;
0791: tmp2 = acb0x + (l + 1) * cw;
0792: tmp2 = (tmp2 > sb.ulcx + sb.w) ? sb.ulcx
0793: + sb.w
0794: : tmp2;
0795: cb.w = tmp2 - tmp1;
0796: tmp1 = acb0y + k * ch;
0797: tmp1 = (tmp1 > sb.ulcy) ? tmp1
0798: : sb.ulcy;
0799: tmp2 = acb0y + (k + 1) * ch;
0800: tmp2 = (tmp2 > sb.ulcy + sb.h) ? sb.ulcy
0801: + sb.h
0802: : tmp2;
0803: cb.h = tmp2 - tmp1;
0804: ppinfo[c][r][nPrec].cblk[3][k - kstart][l
0805: - lstart] = cb;
0806: } // Horizontal code-blocks
0807: } // Vertical code-blocks
0808: }
0809:
0810: }
0811: } // Horizontal precincts
0812: } // Vertical precincts
0813: }
0814:
0815: /**
0816: * Gets the number of precincts in a given component and resolution level.
0817: *
0818: * @param c Component index
0819: *
0820: * @param r Resolution index
0821: * */
0822: public int getNumPrecinct(int c, int r) {
0823: return numPrec[c][r].x * numPrec[c][r].y;
0824: }
0825:
0826: /**
0827: * Read specified packet head and found length of each code-block's piece
0828: * of codewords as well as number of skipped most significant bit-planes.
0829: *
0830: * @param l layer index
0831: *
0832: * @param r Resolution level index
0833: *
0834: * @param c Component index
0835: *
0836: * @param p Precinct index
0837: *
0838: * @param cbI CBlkInfo array of relevant component and resolution
0839: * level.
0840: *
0841: * @param nb The number of bytes to read in each tile before reaching
0842: * output rate (used by truncation mode)
0843: *
0844: * @return True if specified output rate or EOF is reached.
0845: * */
0846: public boolean readPktHead(int l, int r, int c, int p,
0847: CBlkInfo[][][] cbI, int[] nb) throws IOException {
0848:
0849: CBlkInfo ccb;
0850: int nSeg; // number of segment to read
0851: int cbLen; // Length of cblk's code-words
0852: int ltp; // last truncation point index
0853: int passtype; // coding pass type
0854: TagTreeDecoder tdIncl, tdBD;
0855: int tmp, tmp2, totnewtp, lblockCur, tpidx;
0856: int sumtotnewtp = 0;
0857: Point cbc;
0858: int startPktHead = ehs.getPos();
0859: if (startPktHead >= ehs.length()) {
0860: // EOF reached at the beginning of this packet head
0861: return true;
0862: }
0863: int tIdx = src.getTileIdx();
0864: PktHeaderBitReader bin;
0865: int mend, nend;
0866: int b;
0867: SubbandSyn sb;
0868: SubbandSyn root = src.getSynSubbandTree(tIdx, c);
0869:
0870: // If packed packet headers was used, use separate stream for reading
0871: // of packet headers
0872: if (pph) {
0873: bin = new PktHeaderBitReader(pphbais);
0874: } else {
0875: bin = this .bin;
0876: }
0877:
0878: int mins = (r == 0) ? 0 : 1;
0879: int maxs = (r == 0) ? 1 : 4;
0880:
0881: boolean precFound = false;
0882: for (int s = mins; s < maxs; s++) {
0883: if (p < ppinfo[c][r].length) {
0884: precFound = true;
0885: }
0886: }
0887: if (!precFound) {
0888: return false;
0889: }
0890:
0891: PrecInfo prec = ppinfo[c][r][p];
0892:
0893: // Synchronize for bit reading
0894: bin.sync();
0895:
0896: // If packet is empty there is no info in it (i.e. no code-blocks)
0897: if (bin.readBit() == 0) {
0898: // No code-block is included
0899: cblks = new Vector[maxs + 1];
0900: for (int s = mins; s < maxs; s++) {
0901: cblks[s] = new Vector();
0902: }
0903: pktIdx++;
0904:
0905: // If truncation mode, checks if output rate is reached
0906: // unless ncb quit condition is used in which case headers
0907: // are not counted
0908: if (isTruncMode && maxCB == -1) {
0909: tmp = ehs.getPos() - startPktHead;
0910: if (tmp > nb[tIdx]) {
0911: nb[tIdx] = 0;
0912: return true;
0913: } else {
0914: nb[tIdx] -= tmp;
0915: }
0916: }
0917:
0918: // Read EPH marker if needed
0919: if (ephUsed) {
0920: readEPHMarker(bin);
0921: }
0922: return false;
0923: }
0924:
0925: // Packet is not empty => decode info
0926: // Loop on each subband in this resolution level
0927: if (cblks == null || cblks.length < maxs + 1) {
0928: cblks = new Vector[maxs + 1];
0929: }
0930:
0931: for (int s = mins; s < maxs; s++) {
0932: if (cblks[s] == null) {
0933: cblks[s] = new Vector();
0934: } else {
0935: cblks[s].removeAllElements();
0936: }
0937: sb = (SubbandSyn) root.getSubbandByIdx(r, s);
0938: // No code-block in this precinct
0939: if (prec.nblk[s] == 0) {
0940: // Go to next subband
0941: continue;
0942: }
0943:
0944: tdIncl = ttIncl[c][r][p][s];
0945: tdBD = ttMaxBP[c][r][p][s];
0946:
0947: mend = (prec.cblk[s] == null) ? 0 : prec.cblk[s].length;
0948: for (int m = 0; m < mend; m++) { // Vertical code-blocks
0949: nend = (prec.cblk[s][m] == null) ? 0
0950: : prec.cblk[s][m].length;
0951: for (int n = 0; n < nend; n++) { // Horizontal code-blocks
0952: cbc = prec.cblk[s][m][n].idx;
0953: b = cbc.x + cbc.y * sb.numCb.x;
0954:
0955: ccb = cbI[s][cbc.y][cbc.x];
0956:
0957: try {
0958: // If code-block not included in previous layer(s)
0959: if (ccb == null || ccb.ctp == 0) {
0960: if (ccb == null) {
0961: ccb = cbI[s][cbc.y][cbc.x] = new CBlkInfo(
0962: prec.cblk[s][m][n].ulx,
0963: prec.cblk[s][m][n].uly,
0964: prec.cblk[s][m][n].w,
0965: prec.cblk[s][m][n].h, nl);
0966: }
0967: ccb.pktIdx[l] = pktIdx;
0968:
0969: // Read inclusion using tag-tree
0970: tmp = tdIncl.update(m, n, l + 1, bin);
0971: if (tmp > l) { // Not included
0972: continue;
0973: }
0974:
0975: // Read bitdepth using tag-tree
0976: tmp = 1;// initialization
0977: for (tmp2 = 1; tmp >= tmp2; tmp2++) {
0978: tmp = tdBD.update(m, n, tmp2, bin);
0979: }
0980: ccb.msbSkipped = tmp2 - 2;
0981:
0982: // New code-block => at least one truncation point
0983: totnewtp = 1;
0984: ccb.addNTP(l, 0);
0985:
0986: // Check whether ncb quit condition is reached
0987: ncb++;
0988: if (maxCB != -1 && !ncbQuit && ncb == maxCB) {
0989: // ncb quit contidion reached
0990: ncbQuit = true;
0991: tQuit = tIdx;
0992: cQuit = c;
0993: sQuit = s;
0994: rQuit = r;
0995: xQuit = cbc.x;
0996: yQuit = cbc.y;
0997: }
0998:
0999: } else { // If code-block already included in one of
1000: // the previous layers.
1001:
1002: ccb.pktIdx[l] = pktIdx;
1003:
1004: // If not inclused
1005: if (bin.readBit() != 1) {
1006: continue;
1007: }
1008:
1009: // At least 1 more truncation point than
1010: // prev. packet
1011: totnewtp = 1;
1012: }
1013:
1014: // Read new truncation points
1015: if (bin.readBit() == 1) {// if bit is 1
1016: totnewtp++;
1017:
1018: // if next bit is 0 do nothing
1019: if (bin.readBit() == 1) {//if is 1
1020: totnewtp++;
1021:
1022: tmp = bin.readBits(2);
1023: totnewtp += tmp;
1024: // If next 2 bits are not 11 do nothing
1025: if (tmp == 0x3) { //if 11
1026: tmp = bin.readBits(5);
1027: totnewtp += tmp;
1028:
1029: // If next 5 bits are not 11111 do nothing
1030: if (tmp == 0x1F) { //if 11111
1031: totnewtp += bin.readBits(7);
1032: }
1033: }
1034: }
1035: }
1036: ccb.addNTP(l, totnewtp);
1037: sumtotnewtp += totnewtp;
1038: cblks[s].addElement(prec.cblk[s][m][n]);
1039:
1040: // Code-block length
1041:
1042: // -- Compute the number of bit to read to obtain
1043: // code-block length.
1044: // numBits = betaLamda + log2(totnewtp);
1045:
1046: // The length is signalled for each segment in
1047: // addition to the final one. The total length is the
1048: // sum of all segment lengths.
1049:
1050: // If regular termination in use, then there is one
1051: // segment per truncation point present. Otherwise, if
1052: // selective arithmetic bypass coding mode is present,
1053: // then there is one termination per bypass/MQ and
1054: // MQ/bypass transition. Otherwise the only
1055: // termination is at the end of the code-block.
1056: int options = ((Integer) decSpec.ecopts
1057: .getTileCompVal(tIdx, c)).intValue();
1058:
1059: if ((options & OPT_TERM_PASS) != 0) {
1060: // Regular termination in use, one segment per new
1061: // pass (i.e. truncation point)
1062: nSeg = totnewtp;
1063: } else if ((options & OPT_BYPASS) != 0) {
1064: // Selective arithmetic coding bypass coding mode
1065: // in use, but no regular termination 1 segment up
1066: // to the end of the last pass of the 4th most
1067: // significant bit-plane, and, in each following
1068: // bit-plane, one segment upto the end of the 2nd
1069: // pass and one upto the end of the 3rd pass.
1070:
1071: if (ccb.ctp <= FIRST_BYPASS_PASS_IDX) {
1072: nSeg = 1;
1073: } else {
1074: nSeg = 1; // One at least for last pass
1075: // And one for each other terminated pass
1076: for (tpidx = ccb.ctp - totnewtp; tpidx < ccb.ctp - 1; tpidx++) {
1077: if (tpidx >= FIRST_BYPASS_PASS_IDX - 1) {
1078: passtype = (tpidx + NUM_EMPTY_PASSES_IN_MS_BP)
1079: % NUM_PASSES;
1080: if (passtype == 1
1081: || passtype == 2) {
1082: // bypass coding just before MQ
1083: // pass or MQ pass just before
1084: // bypass coding => terminated
1085: nSeg++;
1086: }
1087: }
1088: }
1089: }
1090: } else {
1091: // Nothing special in use, just one segment
1092: nSeg = 1;
1093: }
1094:
1095: // Reads lblock increment (common to all segments)
1096: while (bin.readBit() != 0) {
1097: lblock[c][r][s][cbc.y][cbc.x]++;
1098: }
1099:
1100: if (nSeg == 1) { // Only one segment in packet
1101: cbLen = bin
1102: .readBits(lblock[c][r][s][cbc.y][cbc.x]
1103: + MathUtil.log2(totnewtp));
1104: } else {
1105: // We must read one length per segment
1106: ccb.segLen[l] = new int[nSeg];
1107: cbLen = 0;
1108: int j;
1109: if ((options & OPT_TERM_PASS) != 0) {
1110: // Regular termination: each pass is terminated
1111: for (tpidx = ccb.ctp - totnewtp, j = 0; tpidx < ccb.ctp; tpidx++, j++) {
1112:
1113: lblockCur = lblock[c][r][s][cbc.y][cbc.x];
1114:
1115: tmp = bin.readBits(lblockCur);
1116: ccb.segLen[l][j] = tmp;
1117: cbLen += tmp;
1118: }
1119: } else {
1120: // Bypass coding: only some passes are
1121: // terminated
1122: ltp = ccb.ctp - totnewtp - 1;
1123: for (tpidx = ccb.ctp - totnewtp, j = 0; tpidx < ccb.ctp - 1; tpidx++) {
1124: if (tpidx >= FIRST_BYPASS_PASS_IDX - 1) {
1125: passtype = (tpidx + NUM_EMPTY_PASSES_IN_MS_BP)
1126: % NUM_PASSES;
1127: if (passtype == 0)
1128: continue;
1129:
1130: lblockCur = lblock[c][r][s][cbc.y][cbc.x];
1131: tmp = bin.readBits(lblockCur
1132: + MathUtil.log2(tpidx
1133: - ltp));
1134: ccb.segLen[l][j] = tmp;
1135: cbLen += tmp;
1136: ltp = tpidx;
1137: j++;
1138: }
1139: }
1140: // Last pass has always the length sent
1141: lblockCur = lblock[c][r][s][cbc.y][cbc.x];
1142: tmp = bin.readBits(lblockCur
1143: + MathUtil.log2(tpidx - ltp));
1144: cbLen += tmp;
1145: ccb.segLen[l][j] = tmp;
1146: }
1147: }
1148: ccb.len[l] = cbLen;
1149:
1150: // If truncation mode, checks if output rate is reached
1151: // unless ncb and lbody quit contitions used.
1152: if (isTruncMode && maxCB == -1) {
1153: tmp = ehs.getPos() - startPktHead;
1154: if (tmp > nb[tIdx]) {
1155: nb[tIdx] = 0;
1156: // Remove found information in this code-block
1157: if (l == 0) {
1158: cbI[s][cbc.y][cbc.x] = null;
1159: } else {
1160: ccb.off[l] = ccb.len[l] = 0;
1161: ccb.ctp -= ccb.ntp[l];
1162: ccb.ntp[l] = 0;
1163: ccb.pktIdx[l] = -1;
1164: }
1165: return true;
1166: }
1167: }
1168:
1169: } catch (EOFException e) {
1170: // Remove found information in this code-block
1171: if (l == 0) {
1172: cbI[s][cbc.y][cbc.x] = null;
1173: } else {
1174: ccb.off[l] = ccb.len[l] = 0;
1175: ccb.ctp -= ccb.ntp[l];
1176: ccb.ntp[l] = 0;
1177: ccb.pktIdx[l] = -1;
1178: }
1179: // throw new EOFException();
1180: return true;
1181: }
1182: } // End loop on horizontal code-blocks
1183: } // End loop on vertical code-blocks
1184: } // End loop on subbands
1185:
1186: // Read EPH marker if needed
1187: if (ephUsed) {
1188: readEPHMarker(bin);
1189: }
1190:
1191: pktIdx++;
1192:
1193: // If truncation mode, checks if output rate is reached
1194: if (isTruncMode && maxCB == -1) {
1195: tmp = ehs.getPos() - startPktHead;
1196: if (tmp > nb[tIdx]) {
1197: nb[tIdx] = 0;
1198: return true;
1199: } else {
1200: nb[tIdx] -= tmp;
1201: }
1202: }
1203: return false;
1204: }
1205:
1206: /**
1207: * Reads specificied packet body in order to find offset of each
1208: * code-block's piece of codeword. This use the list of found code-blocks
1209: * in previous red packet head.
1210: *
1211: * @param l layer index
1212: *
1213: * @param r Resolution level index
1214: *
1215: * @param c Component index
1216: *
1217: * @param p Precinct index
1218: *
1219: * @param cbI CBlkInfo array of relevant component and resolution
1220: * level.
1221: *
1222: * @param nb The remainding number of bytes to read from the bit stream in
1223: * each tile before reaching the decoding rate (in truncation mode)
1224: *
1225: * @return True if decoding rate is reached
1226: * */
1227: public boolean readPktBody(int l, int r, int c, int p,
1228: CBlkInfo[][][] cbI, int[] nb) throws IOException {
1229: int curOff = ehs.getPos();
1230: Point curCB;
1231: CBlkInfo ccb;
1232: boolean stopRead = false;
1233: int tIdx = src.getTileIdx();
1234: Point cbc;
1235:
1236: boolean precFound = false;
1237: int mins = (r == 0) ? 0 : 1;
1238: int maxs = (r == 0) ? 1 : 4;
1239: for (int s = mins; s < maxs; s++) {
1240: if (p < ppinfo[c][r].length) {
1241: precFound = true;
1242: }
1243: }
1244: if (!precFound) {
1245: return false;
1246: }
1247:
1248: for (int s = mins; s < maxs; s++) {
1249: for (int numCB = 0; numCB < cblks[s].size(); numCB++) {
1250: cbc = ((CBlkCoordInfo) cblks[s].elementAt(numCB)).idx;
1251: ccb = cbI[s][cbc.y][cbc.x];
1252: ccb.off[l] = curOff;
1253: curOff += ccb.len[l];
1254: try {
1255: ehs.seek(curOff);
1256: } catch (EOFException e) {
1257: if (l == 0) {
1258: cbI[s][cbc.y][cbc.x] = null;
1259: } else {
1260: ccb.off[l] = ccb.len[l] = 0;
1261: ccb.ctp -= ccb.ntp[l];
1262: ccb.ntp[l] = 0;
1263: ccb.pktIdx[l] = -1;
1264: }
1265: throw new EOFException();
1266: }
1267:
1268: // If truncation mode
1269: if (isTruncMode) {
1270: if (stopRead || ccb.len[l] > nb[tIdx]) {
1271: // Remove found information in this code-block
1272: if (l == 0) {
1273: cbI[s][cbc.y][cbc.x] = null;
1274: } else {
1275: ccb.off[l] = ccb.len[l] = 0;
1276: ccb.ctp -= ccb.ntp[l];
1277: ccb.ntp[l] = 0;
1278: ccb.pktIdx[l] = -1;
1279: }
1280: stopRead = true;
1281: }
1282: if (!stopRead) {
1283: nb[tIdx] -= ccb.len[l];
1284: }
1285: }
1286: // If ncb quit condition reached
1287: if (ncbQuit && r == rQuit && s == sQuit
1288: && cbc.x == xQuit && cbc.y == yQuit
1289: && tIdx == tQuit && c == cQuit) {
1290: cbI[s][cbc.y][cbc.x] = null;
1291: stopRead = true;
1292: }
1293: } // Loop on code-blocks
1294: } // End loop on subbands
1295:
1296: // Seek to the end of the packet
1297: ehs.seek(curOff);
1298:
1299: if (stopRead) {
1300: return true;
1301: } else {
1302: return false;
1303: }
1304: }
1305:
1306: /**
1307: * Returns the precinct partition width for the specified component,
1308: * resolution level and tile.
1309: *
1310: * @param t the tile index
1311: *
1312: * @param c The index of the component (between 0 and C-1)
1313: *
1314: * @param r The resolution level, from 0 to L.
1315: *
1316: * @return the precinct partition width for the specified component,
1317: * resolution level and tile.
1318: * */
1319: public final int getPPX(int t, int c, int r) {
1320: return decSpec.pss.getPPX(t, c, r);
1321: }
1322:
1323: /**
1324: * Returns the precinct partition height for the specified component,
1325: * resolution level and tile.
1326: *
1327: * @param t the tile index
1328: *
1329: * @param c The index of the component (between 0 and C-1)
1330: *
1331: * @param rl The resolution level, from 0 to L.
1332: *
1333: * @return the precinct partition height in the specified component, for
1334: * the specified resolution level, for the current tile.
1335: * */
1336: public final int getPPY(int t, int c, int rl) {
1337: return decSpec.pss.getPPY(t, c, rl);
1338: }
1339:
1340: /**
1341: * Try to read a SOP marker and check that its sequence number if not out
1342: * of sequence. If so, an error is thrown.
1343: *
1344: * @param nBytes The number of bytes left to read from each tile
1345: *
1346: * @param p Precinct index
1347: *
1348: * @param r Resolution level index
1349: *
1350: * @param c Component index
1351: * */
1352: public boolean readSOPMarker(int[] nBytes, int p, int c, int r)
1353: throws IOException {
1354: int val;
1355: byte sopArray[] = new byte[6];
1356: int tIdx = src.getTileIdx();
1357: int mins = (r == 0) ? 0 : 1;
1358: int maxs = (r == 0) ? 1 : 4;
1359: boolean precFound = false;
1360: for (int s = mins; s < maxs; s++) {
1361: if (p < ppinfo[c][r].length) {
1362: precFound = true;
1363: }
1364: }
1365: if (!precFound) {
1366: return false;
1367: }
1368:
1369: // If SOP markers are not used, return
1370: if (!sopUsed) {
1371: return false;
1372: }
1373:
1374: // Check if SOP is used for this packet
1375: int pos = ehs.getPos();
1376: if ((short) ((ehs.read() << 8) | ehs.read()) != Markers.SOP) {
1377: ehs.seek(pos);
1378: return false;
1379: }
1380: ehs.seek(pos);
1381:
1382: // If length of SOP marker greater than remaining bytes to read for
1383: // this tile return true
1384: if (nBytes[tIdx] < 6) {
1385: return true;
1386: }
1387: nBytes[tIdx] -= 6;
1388:
1389: // Read marker into array 'sopArray'
1390: ehs.readFully(sopArray, 0, Markers.SOP_LENGTH);
1391:
1392: // Check if this is the correct marker
1393: val = sopArray[0];
1394: val <<= 8;
1395: val |= sopArray[1];
1396: if (val != Markers.SOP) {
1397: throw new Error("Corrupted Bitstream: Could not parse SOP "
1398: + "marker !");
1399: }
1400:
1401: // Check if length is correct
1402: val = (sopArray[2] & 0xff);
1403: val <<= 8;
1404: val |= (sopArray[3] & 0xff);
1405: if (val != 4) {
1406: throw new Error(
1407: "Corrupted Bitstream: Corrupted SOP marker !");
1408: }
1409:
1410: // Check if sequence number if ok
1411: val = (sopArray[4] & 0xff);
1412: val <<= 8;
1413: val |= (sopArray[5] & 0xff);
1414:
1415: if (!pph && val != pktIdx) {
1416: throw new Error("Corrupted Bitstream: SOP marker out of "
1417: + "sequence !");
1418: }
1419: if (pph && val != pktIdx - 1) {
1420: // if packed packet headers are used, packet header was read
1421: // before SOP marker segment
1422: throw new Error("Corrupted Bitstream: SOP marker out of "
1423: + "sequence !");
1424: }
1425: return false;
1426: }
1427:
1428: /**
1429: * Try to read an EPH marker. If it is not possible then an Error is
1430: * thrown.
1431: *
1432: * @param bin The packet header reader to read the EPH marker from
1433: * */
1434: public void readEPHMarker(PktHeaderBitReader bin)
1435: throws IOException {
1436: int val;
1437: byte ephArray[] = new byte[2];
1438:
1439: if (bin.usebais) {
1440: bin.bais.read(ephArray, 0, Markers.EPH_LENGTH);
1441: } else {
1442: bin.in.readFully(ephArray, 0, Markers.EPH_LENGTH);
1443: }
1444:
1445: // Check if this is the correct marker
1446: val = ephArray[0];
1447: val <<= 8;
1448: val |= ephArray[1];
1449: if (val != Markers.EPH) {
1450: throw new Error("Corrupted Bitstream: Could not parse EPH "
1451: + "marker ! ");
1452: }
1453: }
1454:
1455: /**
1456: * Get PrecInfo instance of the specified resolution level, component and
1457: * precinct.
1458: *
1459: * @param c Component index.
1460: *
1461: * @param r Resolution level index.
1462: *
1463: * @param p Precinct index.
1464: * */
1465: public PrecInfo getPrecInfo(int c, int r, int p) {
1466: return ppinfo[c][r][p];
1467: }
1468:
1469: }
|