| java.lang.Object jj2000.j2k.entropy.encoder.MQCoder
MQCoder | public class MQCoder (Code) | | This class implements the MQ arithmetic coder. When initialized a specific
state can be specified for each context, which may be adapted to the
probability distribution that is expected for that context.
The type of length calculation and termination can be chosen at
construction time.
---- Tricks that have been tried to improve speed ----
1) Merging Qe and mPS and doubling the lookup tables
Merge the mPS into Qe, as the sign bit (if Qe>=0 the sense of MPS is 0, if
Qe<0 the sense is 1), and double the lookup tables. The first half of the
lookup tables correspond to Qe>=0 (i.e. the sense of MPS is 0) and the
second half to Qe<0 (i.e. the sense of MPS is 1). The nLPS lookup table is
modified to incorporate the changes in the sense of MPS, by making it jump
from the first to the second half and vice-versa, when a change is
specified by the swicthLM lookup table. See JPEG book, section 13.2, page
225.
There is NO speed improvement in doing this, actually there is a slight
decrease, probably due to the fact that often Q has to be negated. Also the
fact that a brach of the type "if (bit==mPS[li])" is replaced by two
simpler braches of the type "if (bit==0)" and "if (q<0)" may contribute to
that.
2) Removing cT
It is possible to remove the cT counter by setting a flag bit in the high
bits of the C register. This bit will be automatically shifted left
whenever a renormalization shift occurs, which is equivalent to decreasing
cT. When the flag bit reaches the sign bit (leftmost bit), which is
equivalenet to cT==0, the byteOut() procedure is called. This test can be
done efficiently with "c<0" since C is a signed quantity. Care must be
taken in byteOut() to reset the bit in order to not interfere with other
bits in the C register. See JPEG book, page 228.
There is NO speed improvement in doing this. I don't really know why since
the number of operations whenever a renormalization occurs is
decreased. Maybe it is due to the number of extra operations in the
byteOut(), terminate() and getNumCodedBytes() procedures.
3) Change the convention of MPS and LPS.
Making the LPS interval be above the MPS interval (MQ coder convention is
the opposite) can reduce the number of operations along the MPS path. In
order to generate the same bit stream as with the MQ convention the output
bytes need to be modified accordingly. The basic rule for this is that C =
(C'^0xFF...FF)-A, where C is the codestream for the MQ convention and C' is
the codestream generated by this other convention. Note that this affects
bit-stuffing as well.
This has not been tested yet.
4) Removing normalization while loop on MPS path
Since in the MPS path Q is guaranteed to be always greater than 0x4000
(decimal 0.375) it is never necessary to do more than 1 renormalization
shift. Therefore the test of the while loop, and the loop itself, can be
removed.
5) Simplifying test on A register
Since A is always less than or equal to 0xFFFF, the test "(a & 0x8000)==0"
can be replaced by the simplete test "a < 0x8000". This test is simpler in
Java since it involves only 1 operation (although the original test can be
converted to only one operation by smart Just-In-Time compilers)
This change has been integrated in the decoding procedures.
6) Speedup mode
Implemented a method that uses the speedup mode of the MQ-coder if
possible. This should greately improve performance when coding long runs of
MPS symbols that have high probability. However, to take advantage of this,
the entropy coder implementation has to explicetely use it. The generated
bit stream is the same as if no speedup mode would have been used.
Implemented but performance not tested yet.
7) Multiple-symbol coding
Since the time spent in a method call is non-negligable, coding several
symbols with one method call reduces the overhead per coded symbol. The
decodeSymbols() method implements this. However, to take advantage of it,
the implementation of the entropy coder has to explicitely use it.
Implemented but performance not tested yet.
|
Field Summary | |
int[] | I | final public static int | LENGTH_LAZY Identifier for the lazy length calculation. | final public static int | LENGTH_LAZY_GOOD Identifier for a very simple length calculation. | final public static int | LENGTH_NEAR_OPT Identifier for the near optimal length calculation. | final static int | SAVED_INC | final static int | SAVED_LEN | final public static int | TERM_EASY The identifier for the easy termination that is simpler than the
'TERM_NEAR_OPT' one but slightly less efficient. | final public static int | TERM_FULL The identifier fort the termination that uses a full flush. | final public static int | TERM_NEAR_OPT | final public static int | TERM_PRED_ER The identifier for the predictable termination policy for error
resilience. | int | a | int | b | int | c | int | cT | boolean | delFF If a 0xFF byte has been delayed and not yet been written to the output
(in the MQ we can never have more than 1 0xFF byte in a row). | int | initStates | int | ltype The length calculation type to use. | int[] | mPS | final static int | nLPS | final static int | nMPS | int | nSaved Number of saved states. | int | nrOfWrittenBytes The number of written bytes so far, excluding any delayed 0xFF
bytes. | ByteOutputBuffer | out The ByteOutputBuffer used to write the compressed bit stream. | final static int | qe | int | savedA Saved values of the A register. | int | savedB Saved values of the B byte buffer. | int | savedC Saved values of the C register. | int | savedCT Saved values of CT counter. | boolean | savedDelFF Saved values of the delFF (i.e. | final static int | switchLM | int | ttype The termination type to use. |
Constructor Summary | |
public | MQCoder(ByteOutputBuffer oStream, int nrOfContexts, int init) Instantiates a new MQ-coder, with the specified number of contexts and
initial states. |
Method Summary | |
final public void | codeSymbol(int bit, int context) This function performs the arithmetic encoding of one symbol. | final public void | codeSymbols(int[] bits, int[] cX, int n) This function performs the arithmetic encoding of several symbols
together. | final public void | fastCodeSymbols(int bit, int ctxt, int n) This method performs the coding of the symbol 'bit', using context
'ctxt', 'n' times, using the MQ-coder speedup mode if possible.
If the symbol 'bit' is the current more probable symbol (MPS) and
qe[ctxt]<=0x4000, and (A-0x8000)>=qe[ctxt], speedup mode will be
used. | public void | finishLengthCalculation(int rates, int n) Terminates the calculation of the required length for each coding
pass. | final public int | getNumCodedBytes() Returns the number of bytes that are necessary from the compressed
output stream to decode all the symbols that have been coded this
far. | final public int | getNumCtxts() Returns the number of contexts in the arithmetic coder. | final public void | reset() Reinitializes the MQ coder and the underlying 'ByteOutputBuffer' buffer
as if a new object was instantaited. | final public void | resetCtxt(int c) Resets a context to the original probability distribution, and sets its
more probable symbol to 0. | final public void | resetCtxts() Resets all contexts to their original probability distribution and sets
all more probable symbols to 0. | public void | setLenCalcType(int ltype) Set the length calculation type to the specified type
Parameters: ltype - The type of length calculation to use. | public void | setTermType(int ttype) Set termination type to the specified type
Parameters: ttype - The type of termination to use. | public int | terminate() This function flushes the remaining encoded bits and makes sure that
enough information is written to the bit stream to be able to finish
decoding, and then it reinitializes the internal state of the MQ coder
but without modifying the context states. |
I | int[] I(Code) | | The current index of each context
|
LENGTH_LAZY | final public static int LENGTH_LAZY(Code) | | Identifier for the lazy length calculation. The lazy length
calculation is not optimal but is extremely simple.
|
LENGTH_LAZY_GOOD | final public static int LENGTH_LAZY_GOOD(Code) | | Identifier for a very simple length calculation. This provides better
results than the 'LENGTH_LAZY' computation. This is the old length
calculation that was implemented in this class.
|
LENGTH_NEAR_OPT | final public static int LENGTH_NEAR_OPT(Code) | | Identifier for the near optimal length calculation. This calculation
is more complex than the lazy one but provides an almost optimal length
calculation.
|
SAVED_INC | final static int SAVED_INC(Code) | | The increase in length for the arrays to save states
|
SAVED_LEN | final static int SAVED_LEN(Code) | | The initial length of the arrays to save sates
|
TERM_EASY | final public static int TERM_EASY(Code) | | The identifier for the easy termination that is simpler than the
'TERM_NEAR_OPT' one but slightly less efficient.
|
TERM_FULL | final public static int TERM_FULL(Code) | | The identifier fort the termination that uses a full flush. This is
the less efficient termination.
|
TERM_NEAR_OPT | final public static int TERM_NEAR_OPT(Code) | | The identifier for the termination that uses the near optimal length
calculation to terminate the arithmetic codewrod
|
TERM_PRED_ER | final public static int TERM_PRED_ER(Code) | | The identifier for the predictable termination policy for error
resilience. This is the same as the 'TERM_EASY' one but an special
sequence of bits is embodied in the spare bits for error resilience
purposes.
|
a | int a(Code) | | The current interval
|
b | int b(Code) | | The last encoded byte of data
|
c | int c(Code) | | The current bit code
|
cT | int cT(Code) | | The bit code counter
|
delFF | boolean delFF(Code) | | If a 0xFF byte has been delayed and not yet been written to the output
(in the MQ we can never have more than 1 0xFF byte in a row).
|
initStates | int initStates(Code) | | The initial state of each context
|
ltype | int ltype(Code) | | The length calculation type to use. One of 'LENGTH_LAZY',
'LENGTH_LAZY_GOOD', 'LENGTH_NEAR_OPT'.
|
mPS | int[] mPS(Code) | | The current most probable signal for each context
|
nLPS | final static int nLPS(Code) | | The indexes of the next LPS
|
nMPS | final static int nMPS(Code) | | The indexes of the next MPS
|
nSaved | int nSaved(Code) | | Number of saved states. Used for the LENGTH_NEAR_OPT length
calculation.
|
nrOfWrittenBytes | int nrOfWrittenBytes(Code) | | The number of written bytes so far, excluding any delayed 0xFF
bytes. Upon initialization it is -1 to indicated that the byte buffer
'b' is empty as well.
|
qe | final static int qe(Code) | | The data structures containing the probabilities for the LPS
|
savedA | int savedA(Code) | | Saved values of the A register. Used for the LENGTH_NEAR_OPT length
calculation.
|
savedB | int savedB(Code) | | Saved values of the B byte buffer. Used for the LENGTH_NEAR_OPT length
calculation.
|
savedC | int savedC(Code) | | Saved values of the C register. Used for the LENGTH_NEAR_OPT length
calculation.
|
savedCT | int savedCT(Code) | | Saved values of CT counter. Used for the LENGTH_NEAR_OPT length
calculation.
|
savedDelFF | boolean savedDelFF(Code) | | Saved values of the delFF (i.e. delayed 0xFF) state. Used for the
LENGTH_NEAR_OPT length calculation.
|
switchLM | final static int switchLM(Code) | | Whether LPS and MPS should be switched
|
ttype | int ttype(Code) | | The termination type to use. One of 'TERM_FULL', 'TERM_NEAR_OPT',
'TERM_EASY' or 'TERM_PRED_ER'.
|
MQCoder | public MQCoder(ByteOutputBuffer oStream, int nrOfContexts, int init)(Code) | | Instantiates a new MQ-coder, with the specified number of contexts and
initial states. The compressed bytestream is written to the 'oStream'
object.
Parameters: oStream - where to output the compressed data Parameters: nrOfContexts - The number of contexts used Parameters: init - The initial state for each context. A reference is kept tothis array to reinitialize the contexts whenever 'reset()' or'resetCtxts()' is called. |
codeSymbol | final public void codeSymbol(int bit, int context)(Code) | | This function performs the arithmetic encoding of one symbol. The
function receives a bit that is to be encoded and a context with which
to encode it.
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.
Parameters: bit - The symbol to be encoded, must be 0 or 1. Parameters: context - the context with which to encode the symbol. |
codeSymbols | final public void codeSymbols(int[] bits, int[] cX, int n)(Code) | | This function performs the arithmetic encoding of several symbols
together. The function receives an array of symbols that are to be
encoded and an array containing the contexts with which to encode them.
The advantage of using this function is that the cost of the method
call is amortized by the number of coded symbols per method call.
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.
Parameters: bits - An array containing the symbols to be encoded. Validsymbols are 0 and 1. Parameters: cX - The context for each of the symbols to be encoded Parameters: n - The number of symbols to encode. |
fastCodeSymbols | final public void fastCodeSymbols(int bit, int ctxt, int n)(Code) | | This method performs the coding of the symbol 'bit', using context
'ctxt', 'n' times, using the MQ-coder speedup mode if possible.
If the symbol 'bit' is the current more probable symbol (MPS) and
qe[ctxt]<=0x4000, and (A-0x8000)>=qe[ctxt], speedup mode will be
used. Otherwise the normal mode will be used. The speedup mode can
significantly improve the speed of arithmetic coding when several MPS
symbols, with a high probability distribution, must be coded with the
same context. The generated bit stream is the same as if the normal mode
was used.
This method is also faster than the 'codeSymbols()' and
'codeSymbol()' ones, for coding the same symbols with the same context
several times, when speedup mode can not be used, although not
significantly.
Parameters: bit - The symbol do code, 0 or 1. Parameters: ctxt - The context to us in coding the symbol Parameters: n - The number of times that the symbol must be coded. |
finishLengthCalculation | public void finishLengthCalculation(int rates, int n)(Code) | | Terminates the calculation of the required length for each coding
pass. This method must be called just after the 'terminate()' one has
been called for each terminated MQ segment.
The values in 'rates' must have been compensated for any offset due
to previous terminated segments, so that the correct index to the
stored coded data is used.
Parameters: rates - The array containing the values returned by'getNumCodedBytes()' for each coding pass. Parameters: n - The index in the 'rates' array of the last terminated length. |
getNumCodedBytes | final public int getNumCodedBytes()(Code) | | Returns the number of bytes that are necessary from the compressed
output stream to decode all the symbols that have been coded this
far. The number of returned bytes does not include anything coded
previous to the last time the 'terminate()' or 'reset()' methods where
called.
The values returned by this method are then to be used in finishing
the length calculation with the 'finishLengthCalculation()' method,
after compensation of the offset in the number of bytes due to previous
terminated segments.
This method should not be called if the current coding pass is to be
terminated. The 'terminate()' method should be called instead.
The calculation is done based on the type of length calculation
specified at the constructor.
The number of bytes in the compressed output stream necessaryto decode all the information coded this far. |
getNumCtxts | final public int getNumCtxts()(Code) | | Returns the number of contexts in the arithmetic coder.
The number of contexts |
reset | final public void reset()(Code) | | Reinitializes the MQ coder and the underlying 'ByteOutputBuffer' buffer
as if a new object was instantaited. All the data in the
'ByteOutputBuffer' buffer is erased and the state and contexts of the
MQ coder are reinitialized). Additionally any saved MQ states are
discarded.
|
resetCtxt | final public void resetCtxt(int c)(Code) | | Resets a context to the original probability distribution, and sets its
more probable symbol to 0.
Parameters: c - The number of the context (it starts at 0). |
resetCtxts | final public void resetCtxts()(Code) | | Resets all contexts to their original probability distribution and sets
all more probable symbols to 0.
|
setLenCalcType | public void setLenCalcType(int ltype)(Code) | | Set the length calculation type to the specified type
Parameters: ltype - The type of length calculation to use. One of'LENGTH_LAZY', 'LENGTH_LAZY_GOOD' or 'LENGTH_NEAR_OPT'. |
setTermType | public void setTermType(int ttype)(Code) | | Set termination type to the specified type
Parameters: ttype - The type of termination to use. One of 'TERM_FULL','TERM_NEAR_OPT', 'TERM_EASY' or 'TERM_PRED_ER'. |
terminate | public int terminate()(Code) | | This function flushes the remaining encoded bits and makes sure that
enough information is written to the bit stream to be able to finish
decoding, and then it reinitializes the internal state of the MQ coder
but without modifying the context states.
After calling this method the 'finishLengthCalculation()' method
should be called, after cmopensating the returned length for the length
of previous coded segments, so that the length calculation is finalized.
The type of termination used depends on the one specified at the
constructor.
The length of the arithmetic codeword after termination, inbytes. |
|
|