📄 mqdecoder.java
字号:
byteIn(); la<<=1; c<<=1; cT--; }while(la < 0x8000); // -- End renormalization } // -- End MPS Exchange a = la; } } else { la = a; c -= (la<<16); // -- LPS Exchange if(la < q){ la = q; bits[i] = mPS[ctxt]; I[ctxt] = nMPS[index]; // -- Renormalize (MPS: no need for while loop) if(cT==0) byteIn(); la<<=1; c<<=1; cT--; // -- End renormalization } else { la = q; bits[i] = 1-mPS[ctxt]; if(switchLM[index] == 1) mPS[ctxt] = 1-mPS[ctxt]; I[ctxt] = nLPS[index]; // -- Renormalize do{ if(cT==0) byteIn(); la<<=1; c<<=1; cT--; } while (la < 0x8000); // -- End renormalization } // -- End LPS Exchange a = la; } } } /** * Arithmetically decodes one symbol from the bit stream with the given * context and returns its decoded value. * * <P>Each context has a current MPS and an index describing what the * current probability is for the LPS. Each bit is encoded and if the * probability of the LPS exceeds .5, the MPS and LPS are switched. * * @param context The context to use in decoding the symbol * * @return The decoded symbol, 0 or 1. * * */ public final int decodeSymbol(int context){ int q; int la; int index; int decision; index = I[context]; q = qe[index]; // NOTE: (a < 0x8000) is equivalent to ((a & 0x8000)==0) // since 'a' is always less than or equal to 0xFFFF // NOTE: conditional exchange guarantees that A for MPS is // always greater than 0x4000 (i.e. 0.375) // => one renormalization shift is enough for MPS // => no need to do a renormalization while loop for MPS a -= q; if ((c>>>16) < a) { if(a >= 0x8000){ decision = mPS[context]; } else { la = a; // -- MPS Exchange if(la >= q){ decision = mPS[context]; I[context] = nMPS[index]; // -- Renormalize (MPS: no need for while loop) if(cT==0) byteIn(); la<<=1; c<<=1; cT--; // -- End renormalization } else{ decision = 1-mPS[context]; if(switchLM[index]==1) mPS[context] = 1-mPS[context]; I[context] = nLPS[index]; // -- Renormalize do{ if(cT==0) byteIn(); la<<=1; c<<=1; cT--; }while(la < 0x8000); // -- End renormalization } // -- End MPS Exchange a = la; } } else { la = a; c -= (la<<16); // -- LPS Exchange if(la < q){ la = q; decision = mPS[context]; I[context] = nMPS[index]; // -- Renormalize (MPS: no need for while loop) if(cT==0) byteIn(); la<<=1; c<<=1; cT--; // -- End renormalization } else { la = q; decision = 1-mPS[context]; if(switchLM[index] == 1) mPS[context] = 1-mPS[context]; I[context] = nLPS[index]; // -- Renormalize do{ if(cT==0) byteIn(); la<<=1; c<<=1; cT--; } while (la < 0x8000); // -- End renormalization } // -- End LPS Exchange a = la; } return decision; } /** * Checks for past errors in the decoding process using the predictable * error resilient termination. This works only if the encoder used the * predictable error resilient MQ termination, otherwise it reports wrong * results. If an error is detected it means that the MQ bit stream has * been wrongly decoded or that the MQ terminated segment length is too * long. If no errors are detected it does not necessarily mean that the * MQ bit stream has been correctly decoded. * * @return True if errors are found, false otherwise. * */ public boolean checkPredTerm() { int k; // Number of bits that where added in the termination process int q; // 1) if everything has been OK, 'b' must be 0xFF if a terminating // marker has not yet been found if (b != 0xFF && !markerFound) return true; // 2) if cT is not 0, we must have already reached the terminating // marker if (cT != 0 && !markerFound) return true; // 3) If cT is 1 there where no spare bits at the encoder, this is all // that we can check if (cT == 1) return false; // 4) if cT is 0, then next byte must be the second byte of a // terminating marker (i.e. larger than 0x8F) if the terminating // marker has not been reached yet if (cT == 0) { if (!markerFound) { // Get next byte and check b=in.read()&0xFF; if (b <= 0x8F) return true; } // Adjust cT for last byte cT = 8; } // 5) Now we can calculate the number 'k' of bits having error // resilience information, which is the number of bits left to // normalization in the C register, minus 1. k = cT-1; // 6) The predictable termination policy is as if an LPS interval was // coded that caused a renormalization of 'k' bits, before the // termination marker started // We first check if an LPS is decoded, that causes a renormalization // of 'k' bits. Worst case is smallest LPS probability 'q' that causes // a renormalization of 'k' bits. q = 0x8000>>k; // Check that we can decode an LPS interval of probability 'q' a -= q; if ((c>>>16) < a) { // Error: MPS interval decoded return true; } // OK: LPS interval decoded c -= (a<<16); // -- LPS Exchange // Here 'a' can not be smaller than 'q' because the minimum value // for 'a' is 0x8000-0x4000=0x4000 and 'q' is set to a value equal // to or smaller than that. a = q; // -- Renormalize do{ if(cT==0) byteIn(); a<<=1; c<<=1; cT--; } while (a < 0x8000); // -- End renormalization // -- End LPS Exchange // 7) Everything seems OK, we have checked the C register for the LPS // symbols and ensured that it is followed by bits synthetized by the // termination marker. return false; } /** * This function gets one byte of compressed bits from the in-stream. * the byte is added to c. If the byte is 0xFF and the next byte is greater * than 0x8F, the byte after 0xFF is a marker. * * * */ private void byteIn(){ if(!markerFound){ if(b==0xFF){ b=in.read()&0xFF; // Convert EOFs (-1) to 0xFF if(b>0x8F){ markerFound=true; // software-convention decoder: c unchanged cT=8; }else{ c += 0xFE00 - (b<<9); cT=7; } }else{ b=in.read()&0xFF; // Convert EOFs (-1) to 0xFF c += 0xFF00 - (b<<8); cT=8; } } else{ // software-convention decoder: c unchanged cT=8; } } /** * Returns the number of contexts in the arithmetic coder. * * @return The number of contexts * * **/ public final int getNumCtxts(){ return I.length; } /** * Resets a context to the original probability distribution. * * @param c The number of the context (it starts at 0). * * * */ public final void resetCtxt(int c){ I[c] = initStates[c]; mPS[c] = 0; } /** * Resets a context to the original probability distribution. The * original probability distribution depends on the actual * implementation of the arithmetic coder or decoder. * * @param c The index of the context (it starts at 0). * * * */ public final void resetCtxts(){ System.arraycopy(initStates,0,I,0,I.length); ArrayUtil.intArraySet(mPS,0); } /** * Resets the MQ decoder to start a new segment. This is like recreating a * new MQDecoder object with new input data. * * @param buf The byte array containing the MQ encoded data. If null the * current byte array is assumed. * * @param off The index of the first element in 'buf' to be decoded. If * negative the byte just after the previous segment is assumed, only * valid if 'buf' is null. * * @param len The number of bytes in 'buf' to be decoded. Any subsequent * bytes are taken to be 0xFF. * * * */ public final void nextSegment(byte buf[], int off, int len) { // Set the new input in.setByteArray(buf,off,len); // Reinitialize MQ init(); } /** * Returns the underlying 'ByteInputBuffer' from where the MQ * coded input bytes are read. * * @return The underlying ByteInputBuffer. * * */ public ByteInputBuffer getByteInputBuffer() { return in; } /** * Initializes the state of the MQ coder, without modifying the current * context states. It sets the registers (A,C,B) and the "marker found" * state to the initial state, to start the decoding of a new segment. * * <P>To have a complete reset of the MQ (as if a new MQDecoder object was * created) 'resetCtxts()' should be called after this method. * * * */ private void init() { // --- INITDEC markerFound = false; // Read first byte b=in.read()&0xFF; // Software conventions decoder c=(b^0xFF)<<16; byteIn(); c=c<<7; cT=cT-7; a=0x8000; // End of INITDEC --- }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -