ebcotrateallocator.java
来自「jpeg2000编解码」· Java 代码 · 共 1,684 行 · 第 1/5 页
JAVA
1,684 行
// Tile's coordinates in the reduced resolution image // domain trx0 = (int)Math.ceil(tcx0/(double)(1<<(mrl-1-r))); try0 = (int)Math.ceil(tcy0/(double)(1<<(mrl-1-r))); trx1 = (int)Math.ceil(tcx1/(double)(1<<(mrl-1-r))); try1 = (int)Math.ceil(tcy1/(double)(1<<(mrl-1-r))); // Calculate the maximum number of precincts for each // resolution level taking into account tile specific // options. double twoppx = (double)encSpec.pss.getPPX(t,c,r); double twoppy = (double)encSpec.pss.getPPY(t,c,r); numPrec[t][c][r] = new Coord(); if (trx1>trx0) { numPrec[t][c][r].x = (int)Math.ceil((trx1-cb0x)/twoppx) - (int)Math.floor((trx0-cb0x)/twoppx); } else { numPrec[t][c][r].x = 0; } if (try1>try0) { numPrec[t][c][r].y = (int)Math.ceil((try1-cb0y)/twoppy) - (int)Math.floor((try0-cb0y)/(double)twoppy); } else { numPrec[t][c][r].y = 0; } minsbi = (r==0) ? 0 : 1; maxsbi = (r==0) ? 1 : 4; cblks[t][c][r] = new CBlkRateDistStats[maxsbi][]; for(l=0; l<numLayers; l++) { truncIdxs[t][l][c][r] = new int[maxsbi][]; } for(s=minsbi; s<maxsbi; s++) { // loop on subbands //Get the number of blocks in the current subband sb2 = (SubbandAn)sb.getSubbandByIdx(r,s); ncblks = sb2.numCb; cblkPerSubband = ncblks.x*ncblks.y; cblks[t][c][r][s] = new CBlkRateDistStats[cblkPerSubband]; for(l=0; l<numLayers; l++) { truncIdxs[t][l][c][r][s] = new int[cblkPerSubband]; for(i=0; i<cblkPerSubband; i++) { truncIdxs[t][l][c][r][s][i] = -1; } } } // End loop on subbands } // End lopp on resolution levels } // End loop on components if(t!=nt-1) { src.nextTile(); } } // End loop on tiles // Check if encryption is needed for eventual scrambled code-blocks String str = pl.getParameter("Sprivate_key"); if(str!=null) { StringTokenizer stk = new StringTokenizer(str); if(stk.countTokens()==2) { rsaExp = new BigInteger(stk.nextToken()); rsaMod = new BigInteger(stk.nextToken()); BigInteger mOne = new BigInteger("-1"); if(rsaExp.equals(mOne) || rsaMod.equals(mOne)) { isEncryptionNeeded = false; } else { isEncryptionNeeded = true; } } } //Initialize the packet encoder pktEnc = new PktEncoder(src,encSpec,numPrec,pl); // The layers array has to be initialized after the constructor since // it is needed that the bit stream header has been entirely written } /** * Prints the timing information, if collected, and calls 'finalize' on * the super class. * */ public void finalize() throws Throwable { if(DO_TIMING) { StringBuffer sb; sb = new StringBuffer("EBCOTRateAllocator wall clock times:\n"); sb.append(" initialization: "); sb.append(initTime); sb.append(" ms\n"); sb.append(" layer building: "); sb.append(buildTime); sb.append(" ms\n"); sb.append(" final writing: "); sb.append(writeTime); sb.append(" ms"); FacilityManager.getMsgLogger(). printmsg(MsgLogger.INFO,sb.toString()); } super.finalize(); } /** * Runs the rate allocation algorithm and writes the data to the bit * stream writer object provided to the constructor. * */ public void runAndWrite() throws IOException { //Now, run the rate allocation buildAndWriteLayers(); } /** * Initializes the layers array. This must be called after the main header * has been entirely written or simulated, so as to take its overhead into * account. This method will get all the code-blocks and then initialize * the target bitrates for each layer, according to the specifications. * */ public void initialize() throws IOException { int n,i,l; int ho; // The header overhead (in bytes) float np;// The number of pixels divided by the number of bits per byte double ls; // Step for log-scale double basebytes; int lastbytes,newbytes,nextbytes; int loopnlyrs; int minlsz; // The minimum allowable number of bytes in a layer int totenclength; int maxpkt; int numTiles = src.getNumTiles(); int numComps = src.getNumComps(); int numLvls; int avgPktLen; long stime = 0L; // Start by getting all the code-blocks, we need this in order to have // an idea of the total encoded bitrate. getAllCodeBlocks(); if(DO_TIMING) stime = System.currentTimeMillis(); // Now get the total encoded length totenclength = RDSlopesRates[0]; // all the encoded data // Make a rough estimation of the packet head overhead, as 2 bytes per // packet in average (plus EPH / SOP) , and add that to the total // encoded length for(int t=0; t<numTiles; t++) { avgPktLen = 2; // Add SOP length if set if(((String)encSpec.sops.getTileDef(t)).equalsIgnoreCase("on")) { avgPktLen += Markers.SOP_LENGTH; } // Add EPH length if set if(((String)encSpec.ephs.getTileDef(t)).equalsIgnoreCase("on")) { avgPktLen += Markers.EPH_LENGTH; } for(int c=0; c<numComps; c++) { numLvls = src.getAnSubbandTree(t,c).resLvl+1; if( !src.precinctPartitionUsed(c,t) ) { // Precinct partition is not used so there is only // one packet per resolution level/layer totenclength += numLayers*avgPktLen*numLvls; } else { // Precinct partition is used so for each // component/tile/resolution level, we get the maximum // number of packets for(int rl=0; rl<numLvls; rl++) { maxpkt = numPrec[t][c][rl].x*numPrec[t][c][rl].y; totenclength += numLayers*avgPktLen*maxpkt; } } } // End loop on components } // End loop on tiles // If any layer specifies more than 'totenclength' as its target // length then 'totenclength' is used. This is to prevent that // estimated layers get excessively large target lengths due to an // excessively large target bitrate. At the end the last layer is set // to the target length corresponding to the overall target // bitrate. Thus, 'totenclength' can not limit the total amount of // encoded data, as intended. ho = headEnc.getLength(); np = src.getImgWidth()*src.getImgHeight()/8f; // SOT marker must be taken into account for(int t=0; t<numTiles; t++) { headEnc.reset(); headEnc.encodeTilePartHeader(0,t); ho += headEnc.getLength(); } // Seeds of scrambled code-blocks ho += cblkProtOver; estimHeadOver = ho; layers = new EBCOTLayer[numLayers]; for (n = numLayers-1; n>=0; n--) { layers[n] = new EBCOTLayer(); } minlsz = 0; // To keep compiler happy for(int t=0; t<numTiles; t++) { for(int c=0; c<numComps; c++) { numLvls = src.getAnSubbandTree(t,c).resLvl+1; if( !src.precinctPartitionUsed(c,t) ) { // Precinct partition is not used minlsz += MIN_AVG_PACKET_SZ*numLvls; } else { // Precinct partition is used for (int rl=0; rl<numLvls; rl++) { maxpkt = numPrec[t][c][rl].x*numPrec[t][c][rl].y; minlsz += MIN_AVG_PACKET_SZ*maxpkt; } } } // End loop on components } // End loop on tiles // Initialize layers n = 0; i = 0; lastbytes = 0; while(n<numLayers-1) { // At an optimized layer basebytes = Math.floor(lyrSpec.getTargetBitrate(i)*np); if(i < lyrSpec.getNOptPoints()-1) { nextbytes = (int) (lyrSpec.getTargetBitrate(i+1)*np); // Limit target length to 'totenclength' if (nextbytes > totenclength) nextbytes = totenclength; } else { nextbytes = 1; } loopnlyrs = lyrSpec.getExtraLayers(i)+1; ls = Math.exp(Math.log((double)nextbytes/basebytes)/loopnlyrs); layers[n].optimize = true; for(l=0; l<loopnlyrs; l++) { newbytes = (int)basebytes - lastbytes - ho; if(newbytes<minlsz) { // Skip layer (too small) basebytes *= ls; numLayers--; continue; } lastbytes = (int)basebytes - ho; layers[n].maxBytes = lastbytes; basebytes *= ls; n++; } i++; // Goto next optimization point } // Ensure minimum size of last layer (this one determines overall // bitrate) n = numLayers-2; nextbytes = (int) (lyrSpec.getTotBitrate()*np) - ho; newbytes = nextbytes - ((n>=0) ? layers[n].maxBytes : 0); while(newbytes<minlsz) { if(numLayers==1) { if(newbytes<=0) { throw new IllegalArgumentException("Overall target bitrate too "+ "low, given the current "+ "bit stream header overhead"); } break; } // Delete last layer numLayers--; n--; newbytes = nextbytes - ((n>=0) ? layers[n].maxBytes : 0); } // Set last layer to the overall target bitrate n++; layers[n].maxBytes = nextbytes; layers[n].optimize = true; // Re-initialize progression order changes if needed Default values Progression[] prog1,prog2; prog1 = (Progression[])encSpec.pocs.getDefault(); int nValidProg = prog1.length; for(int prg=0; prg<prog1.length; prg++) { if(prog1[prg].lye>numLayers){ prog1[prg].lye = numLayers; } } if(nValidProg==0) { throw new Error("Unable to initialize rate allocator: No "+ "default progression type has been defined."); } // Tile specific values for(int t=0; t<numTiles; t++) { if(encSpec.pocs.isTileSpecified(t)) { prog1 = (Progression[])encSpec.pocs.getTileDef(t); nValidProg = prog1.length; for(int prg=0; prg<prog1.length; prg++) { if(prog1[prg].lye>numLayers) { prog1[prg].lye = numLayers; } } if(nValidProg==0) { throw new Error("Unable to initialize rate allocator:"+ " No default progression type has been "+ "defined for tile "+t); } } } // End loop on tiles if(DO_TIMING) initTime += System.currentTimeMillis()-stime; } /** * This method gets all the coded code-blocks from the EBCOT entropy coder * for every component and every tile. Each coded code-block is stored in * a 5D array according to the component, the resolution level, the tile, * the subband it belongs and its position in the subband. * * <P> For each code-block, the valid slopes are computed and converted * into the mantissa-exponent representation. * */ private void getAllCodeBlocks() { int numComps, numTiles, numBytes; int c, r, t, s, sidx, k; int slope; SubbandAn subb; CBlkRateDistStats ccb = null; Coord ncblks = null; int last_sidx; float fslope; long stime = 0L; maxSlope = 0f;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?