public virtual bool readPktHead(int l, int r, int c, int p, CBlkInfo[][][] cbI, int[] nb)
{
CBlkInfo ccb;
int nSeg; // number of segment to read
int cbLen; // Length of cblk's code-words
int ltp; // last truncation point index
int passtype; // coding pass type
TagTreeDecoder tdIncl, tdBD;
int tmp, tmp2, totnewtp, lblockCur, tpidx;
int sumtotnewtp = 0;
Coord cbc;
int startPktHead = ehs.Pos;
if (startPktHead >= ehs.length())
{
// EOF reached at the beginning of this packet head
return true;
}
int tIdx = src.TileIdx;
PktHeaderBitReader bin;
int mend, nend;
int b;
SubbandSyn sb;
SubbandSyn root = src.getSynSubbandTree(tIdx, c);
// If packed packet headers was used, use separate stream for reading
// of packet headers
if (pph)
{
bin = new PktHeaderBitReader(pphbais);
}
else
{
bin = this.bin;
}
int mins = (r == 0)?0:1;
int maxs = (r == 0)?1:4;
bool precFound = false;
for (int s = mins; s < maxs; s++)
{
if (p < ppinfo[c][r].Length)
{
precFound = true;
}
}
if (!precFound)
{
return false;
}
PrecInfo prec = ppinfo[c][r][p];
// Synchronize for bit reading
bin.sync();
// If packet is empty there is no info in it (i.e. no code-blocks)
if (bin.readBit() == 0)
{
// No code-block is included
cblks = new List<CBlkCoordInfo>[maxs + 1];
for (int s = mins; s < maxs; s++)
{
cblks[s] = new List<CBlkCoordInfo>(10);
}
pktIdx++;
// If truncation mode, checks if output rate is reached
// unless ncb quit condition is used in which case headers
// are not counted
if (isTruncMode && maxCB == - 1)
{
tmp = ehs.Pos - startPktHead;
if (tmp > nb[tIdx])
{
nb[tIdx] = 0;
return true;
}
else
{
nb[tIdx] -= tmp;
}
}
// Read EPH marker if needed
if (ephUsed)
{
readEPHMarker(bin);
}
return false;
}
// Packet is not empty => decode info
// Loop on each subband in this resolution level
if (cblks == null || cblks.Length < maxs + 1)
{
cblks = new List<CBlkCoordInfo>[maxs + 1];
}
for (int s = mins; s < maxs; s++)
{
if (cblks[s] == null)
{
cblks[s] = new List<CBlkCoordInfo>(10);
}
else
{
cblks[s].Clear();
}
sb = (SubbandSyn) root.getSubbandByIdx(r, s);
// No code-block in this precinct
if (prec.nblk[s] == 0)
{
// Go to next subband
continue;
}
tdIncl = ttIncl[c][r][p][s];
tdBD = ttMaxBP[c][r][p][s];
mend = (prec.cblk[s] == null)?0:prec.cblk[s].Length;
for (int m = 0; m < mend; m++)
{
// Vertical code-blocks
nend = (prec.cblk[s][m] == null)?0:prec.cblk[s][m].Length;
for (int n = 0; n < nend; n++)
{
// Horizontal code-blocks
cbc = prec.cblk[s][m][n].idx;
b = cbc.x + cbc.y * sb.numCb.x;
ccb = cbI[s][cbc.y][cbc.x];
try
{
// If code-block not included in previous layer(s)
if (ccb == null || ccb.ctp == 0)
{
if (ccb == null)
{
ccb = cbI[s][cbc.y][cbc.x] = new CBlkInfo(prec.cblk[s][m][n].ulx, prec.cblk[s][m][n].uly, prec.cblk[s][m][n].w, prec.cblk[s][m][n].h, nl);
}
ccb.pktIdx[l] = pktIdx;
// Read inclusion using tag-tree
tmp = tdIncl.update(m, n, l + 1, bin);
if (tmp > l)
{
// Not included
continue;
}
// Read bitdepth using tag-tree
tmp = 1; // initialization
for (tmp2 = 1; tmp >= tmp2; tmp2++)
{
tmp = tdBD.update(m, n, tmp2, bin);
}
ccb.msbSkipped = tmp2 - 2;
// New code-block => at least one truncation point
totnewtp = 1;
ccb.addNTP(l, 0);
// Check whether ncb quit condition is reached
ncb++;
if (maxCB != - 1 && !ncbQuit && ncb == maxCB)
{
// ncb quit contidion reached
ncbQuit = true;
tQuit = tIdx;
cQuit = c;
sQuit = s;
rQuit = r;
xQuit = cbc.x;
yQuit = cbc.y;
}
}
else
{
// If code-block already included in one of
// the previous layers.
ccb.pktIdx[l] = pktIdx;
// If not inclused
if (bin.readBit() != 1)
{
continue;
}
// At least 1 more truncation point than
// prev. packet
totnewtp = 1;
}
// Read new truncation points
if (bin.readBit() == 1)
{
// if bit is 1
totnewtp++;
// if next bit is 0 do nothing
if (bin.readBit() == 1)
{
//if is 1
totnewtp++;
tmp = bin.readBits(2);
totnewtp += tmp;
// If next 2 bits are not 11 do nothing
if (tmp == 0x3)
{
//if 11
tmp = bin.readBits(5);
totnewtp += tmp;
// If next 5 bits are not 11111 do nothing
if (tmp == 0x1F)
{
//if 11111
totnewtp += bin.readBits(7);
}
}
}
}
ccb.addNTP(l, totnewtp);
sumtotnewtp += totnewtp;
cblks[s].Add(prec.cblk[s][m][n]);
// Code-block length
// -- Compute the number of bit to read to obtain
// code-block length.
// numBits = betaLamda + log2(totnewtp);
// The length is signalled for each segment in
// addition to the final one. The total length is the
// sum of all segment lengths.
// If regular termination in use, then there is one
// segment per truncation point present. Otherwise, if
// selective arithmetic bypass coding mode is present,
// then there is one termination per bypass/MQ and
// MQ/bypass transition. Otherwise the only
// termination is at the end of the code-block.
int options = ((System.Int32) decSpec.ecopts.getTileCompVal(tIdx, c));
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
{
// Regular termination in use, one segment per new
// pass (i.e. truncation point)
nSeg = totnewtp;
}
else if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0)
{
// Selective arithmetic coding bypass coding mode
// in use, but no regular termination 1 segment up
// to the end of the last pass of the 4th most
// significant bit-plane, and, in each following
// bit-plane, one segment upto the end of the 2nd
// pass and one upto the end of the 3rd pass.
if (ccb.ctp <= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX)
{
nSeg = 1;
}
else
{
nSeg = 1; // One at least for last pass
// And one for each other terminated pass
for (tpidx = ccb.ctp - totnewtp; tpidx < ccb.ctp - 1; tpidx++)
{
if (tpidx >= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX - 1)
{
passtype = (tpidx + CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_EMPTY_PASSES_IN_MS_BP) % CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES;
if (passtype == 1 || passtype == 2)
{
// bypass coding just before MQ
// pass or MQ pass just before
// bypass coding => terminated
nSeg++;
}
}
}
}
}
else
{
// Nothing special in use, just one segment
nSeg = 1;
}
// Reads lblock increment (common to all segments)
while (bin.readBit() != 0)
{
lblock[c][r][s][cbc.y][cbc.x]++;
}
if (nSeg == 1)
{
// Only one segment in packet
cbLen = bin.readBits(lblock[c][r][s][cbc.y][cbc.x] + MathUtil.log2(totnewtp));
}
else
{
// We must read one length per segment
ccb.segLen[l] = new int[nSeg];
cbLen = 0;
int j;
if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
{
// Regular termination: each pass is terminated
for (tpidx = ccb.ctp - totnewtp, j = 0; tpidx < ccb.ctp; tpidx++, j++)
{
lblockCur = lblock[c][r][s][cbc.y][cbc.x];
tmp = bin.readBits(lblockCur);
ccb.segLen[l][j] = tmp;
cbLen += tmp;
}
}
else
{
// Bypass coding: only some passes are
// terminated
ltp = ccb.ctp - totnewtp - 1;
for (tpidx = ccb.ctp - totnewtp, j = 0; tpidx < ccb.ctp - 1; tpidx++)
{
if (tpidx >= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX - 1)
{
passtype = (tpidx + CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_EMPTY_PASSES_IN_MS_BP) % CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES;
if (passtype == 0)
continue;
lblockCur = lblock[c][r][s][cbc.y][cbc.x];
tmp = bin.readBits(lblockCur + MathUtil.log2(tpidx - ltp));
ccb.segLen[l][j] = tmp;
cbLen += tmp;
ltp = tpidx;
j++;
}
}
// Last pass has always the length sent
lblockCur = lblock[c][r][s][cbc.y][cbc.x];
tmp = bin.readBits(lblockCur + MathUtil.log2(tpidx - ltp));
cbLen += tmp;
ccb.segLen[l][j] = tmp;
}
}
ccb.len[l] = cbLen;
// If truncation mode, checks if output rate is reached
// unless ncb and lbody quit contitions used.
if (isTruncMode && maxCB == - 1)
{
tmp = ehs.Pos - startPktHead;
if (tmp > nb[tIdx])
{
nb[tIdx] = 0;
// Remove found information in this code-block
if (l == 0)
{
cbI[s][cbc.y][cbc.x] = null;
}
else
{
ccb.off[l] = ccb.len[l] = 0;
ccb.ctp -= ccb.ntp[l];
ccb.ntp[l] = 0;
ccb.pktIdx[l] = - 1;
}
return true;
}
}
}
catch (System.IO.EndOfStreamException e)
{
// Remove found information in this code-block
if (l == 0)
{
cbI[s][cbc.y][cbc.x] = null;
}
else
{
ccb.off[l] = ccb.len[l] = 0;
ccb.ctp -= ccb.ntp[l];
ccb.ntp[l] = 0;
ccb.pktIdx[l] = - 1;
}
// throw new EOFException();
return true;
}
} // End loop on horizontal code-blocks
} // End loop on vertical code-blocks
} // End loop on subbands
// Read EPH marker if needed
if (ephUsed)
{
readEPHMarker(bin);
}
pktIdx++;
// If truncation mode, checks if output rate is reached
if (isTruncMode && maxCB == - 1)
{
tmp = ehs.Pos - startPktHead;
if (tmp > nb[tIdx])
{
nb[tIdx] = 0;
return true;
}
else
{
nb[tIdx] -= tmp;
}
}
return false;
}