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