Пример #1
0
        /// <summary> 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.
        /// 
        /// </summary>
        public override void initialize()
        {
            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.NumComps;
            int numLvls;
            int avgPktLen;
            #if DO_TIMING
            long stime = 0L;
            #endif
            // 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.DateTime.Now.Ticks - 621355968000000000) / 10000;
            #endif

            // 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 (((System.String) encSpec.sops.getTileDef(t)).ToUpper().Equals("on".ToUpper()))
                {
                    avgPktLen += CSJ2K.j2k.codestream.Markers.SOP_LENGTH;
                }
                // Add EPH length if set
                if (((System.String) encSpec.ephs.getTileDef(t)).ToUpper().Equals("on".ToUpper()))
                {
                    avgPktLen += CSJ2K.j2k.codestream.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 += num_Layers * 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 += num_Layers * 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.Length;
            np = src.ImgWidth * src.ImgHeight / 8f;

            // SOT marker must be taken into account
            for (int t = 0; t < numTiles; t++)
            {
                headEnc.reset();
                headEnc.encodeTilePartHeader(0, t);
                ho += headEnc.Length;
            }

            layers = new EBCOTLayer[num_Layers];
            for (n = num_Layers - 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 < num_Layers - 1)
            {
                // At an optimized layer
                basebytes = System.Math.Floor(lyrSpec.getTargetBitrate(i) * np);
                if (i < lyrSpec.NOptPoints - 1)
                {
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    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 = System.Math.Exp(System.Math.Log((double) nextbytes / basebytes) / loopnlyrs);
                layers[n].optimize = true;
                for (l = 0; l < loopnlyrs; l++)
                {
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    newbytes = (int) basebytes - lastbytes - ho;
                    if (newbytes < minlsz)
                    {
                        // Skip layer (too small)
                        basebytes *= ls;
                        num_Layers--;
                        continue;
                    }
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    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 = num_Layers - 2;
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            nextbytes = (int) (lyrSpec.TotBitrate * np) - ho;
            newbytes = nextbytes - ((n >= 0)?layers[n].maxBytes:0);
            while (newbytes < minlsz)
            {
                if (num_Layers == 1)
                {
                    if (newbytes <= 0)
                    {
                        throw new System.ArgumentException("Overall target bitrate too " + "low, given the current " + "bit stream header overhead");
                    }
                    break;
                }
                // Delete last layer
                num_Layers--;
                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 removed
            prog1 = (Progression[]) encSpec.pocs.getDefault();
            int nValidProg = prog1.Length;
            for (int prg = 0; prg < prog1.Length; prg++)
            {
                if (prog1[prg].lye > num_Layers)
                {
                    prog1[prg].lye = num_Layers;
                }
            }
            if (nValidProg == 0)
            {
                throw new System.InvalidOperationException("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 > num_Layers)
                        {
                            prog1[prg].lye = num_Layers;
                        }
                    }
                    if (nValidProg == 0)
                    {
                        throw new System.InvalidOperationException("Unable to initialize rate allocator:" + " No default progression type has been " + "defined for tile " + t);
                    }
                }
            } // End loop on tiles

            #if DO_TIMING
            initTime += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime;
            #endif
        }
Пример #2
0
        /// <summary> This function attempts to estimate a rate-distortion slope threshold
        /// which will achieve a target number of code bytes close the
        /// `targetBytes' value.
        /// 
        /// </summary>
        /// <param name="targetBytes">The target number of bytes for the current layer
        /// 
        /// </param>
        /// <param name="lastLayer">The previous layer information.
        /// 
        /// </param>
        /// <returns> The value of the slope threshold for the estimated layer
        /// 
        /// </returns>
        private float estimateLayerThreshold(int targetBytes, EBCOTLayer lastLayer)
        {
            float log_sl1; // The log of the first slope used for interpolation
            float log_sl2; // The log of the second slope used for interpolation
            float log_len1; // The log of the first length used for interpolation
            float log_len2; // The log of the second length used for interpolation
            float log_isl; // The log of the interpolated slope
            float log_ilen; // Log of the interpolated length
            float log_ab; // Log of actual bytes in last layer
            int sidx; // Index into the summary R-D info array
            float log_off; // The log of the offset proportion
            int tlen; // The corrected target layer length
            float lthresh; // The threshold of the last layer
            float eth; // The estimated threshold

            // In order to estimate the threshold we base ourselves in the summary
            // R-D info in RDSlopesRates. In order to use it we must compensate
            // for the overhead of the packet heads. The proportion of overhead is
            // estimated using the last layer simulation results.

            // NOTE: the model used in this method is that the slope varies
            // linearly with the log of the rate (i.e. length).

            // NOTE: the model used in this method is that the distortion is
            // proprotional to a power of the rate. Thus, the slope is also
            // proportional to another power of the rate. This translates as the
            // log of the slope varies linearly with the log of the rate, which is
            // what we use.

            // 1) Find the offset of the length predicted from the summary R-D
            // information, to the actual length by using the last layer.

            // We ensure that the threshold we use for estimation actually
            // includes some data.
            lthresh = lastLayer.rdThreshold;
            if (lthresh > maxSlope)
                lthresh = maxSlope;
            // If the slope of the last layer is too small then we just include
            // all the rest (not possible to do better).
            if (lthresh < FLOAT_ABS_PRECISION)
                return 0f;
            sidx = getLimitedSIndexFromSlope(lthresh);
            // If the index is outside of the summary info array use the last two,
            // or first two, indexes, as appropriate
            if (sidx >= RD_SUMMARY_SIZE - 1)
                sidx = RD_SUMMARY_SIZE - 2;

            // Get the logs of the lengths and the slopes

            if (RDSlopesRates[sidx + 1] == 0)
            {
                // Pathological case, we can not use log of 0. Add
                // RDSlopesRates[sidx]+1 bytes to the rates (just a crude simple
                // solution to this rare case)
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_len1 = (float) System.Math.Log((RDSlopesRates[sidx] << 1) + 1);
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_len2 = (float) System.Math.Log(RDSlopesRates[sidx] + 1);
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_ab = (float) System.Math.Log(lastLayer.actualBytes + RDSlopesRates[sidx] + 1);
            }
            else
            {
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_len1 = (float) System.Math.Log(RDSlopesRates[sidx]);
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_len2 = (float) System.Math.Log(RDSlopesRates[sidx + 1]);
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_ab = (float) System.Math.Log(lastLayer.actualBytes);
            }

            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            log_sl1 = (float) System.Math.Log(getSlopeFromSIndex(sidx));
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            log_sl2 = (float) System.Math.Log(getSlopeFromSIndex(sidx + 1));

            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            log_isl = (float) System.Math.Log(lthresh);

            log_ilen = log_len1 + (log_isl - log_sl1) * (log_len1 - log_len2) / (log_sl1 - log_sl2);

            log_off = log_ab - log_ilen;

            // Do not use negative offsets (i.e. offset proportion larger than 1)
            // since that is probably a sign that our model is off. To be
            // conservative use an offset of 0 (i.e. offset proportiojn 1).
            if (log_off < 0)
                log_off = 0f;

            // 2) Correct the target layer length by the offset.

            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            tlen = (int) (targetBytes / (float) System.Math.Exp(log_off));

            // 3) Find, from the summary R-D info, the thresholds that generate
            // lengths just above and below our corrected target layer length.

            // Look for the index in the summary info array that gives the largest
            // length smaller than the target length
            for (sidx = RD_SUMMARY_SIZE - 1; sidx >= 0; sidx--)
            {
                if (RDSlopesRates[sidx] >= tlen)
                    break;
            }
            sidx++;
            // Correct if out of the array
            if (sidx >= RD_SUMMARY_SIZE)
                sidx = RD_SUMMARY_SIZE - 1;
            if (sidx <= 0)
                sidx = 1;

            // Get the log of the lengths and the slopes that are just above and
            // below the target length.

            if (RDSlopesRates[sidx] == 0)
            {
                // Pathological case, we can not use log of 0. Add
                // RDSlopesRates[sidx-1]+1 bytes to the rates (just a crude simple
                // solution to this rare case)
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_len1 = (float) System.Math.Log(RDSlopesRates[sidx - 1] + 1);
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_len2 = (float) System.Math.Log((RDSlopesRates[sidx - 1] << 1) + 1);
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_ilen = (float) System.Math.Log(tlen + RDSlopesRates[sidx - 1] + 1);
            }
            else
            {
                // Normal case, we can safely take the logs.
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_len1 = (float) System.Math.Log(RDSlopesRates[sidx]);
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_len2 = (float) System.Math.Log(RDSlopesRates[sidx - 1]);
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                log_ilen = (float) System.Math.Log(tlen);
            }

            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            log_sl1 = (float) System.Math.Log(getSlopeFromSIndex(sidx));
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            log_sl2 = (float) System.Math.Log(getSlopeFromSIndex(sidx - 1));

            // 4) Interpolate the two thresholds to find the target threshold.

            log_isl = log_sl1 + (log_ilen - log_len1) * (log_sl1 - log_sl2) / (log_len1 - log_len2);

            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            eth = (float) System.Math.Exp(log_isl);

            // Correct out of bounds results
            if (eth > lthresh)
                eth = lthresh;
            if (eth < FLOAT_ABS_PRECISION)
                eth = 0f;

            // Return the estimated threshold
            return eth;
        }