mirror of
				https://github.com/facebook/zstd.git
				synced 2025-11-03 20:33:11 +03:00 
			
		
		
		
	removed special case all-1 huffman distribution
This commit is contained in:
		@@ -38,10 +38,9 @@
 | 
				
			|||||||
#include "mem.h"
 | 
					#include "mem.h"
 | 
				
			||||||
#include "error_private.h"       /* ERR_*, ERROR */
 | 
					#include "error_private.h"       /* ERR_*, ERROR */
 | 
				
			||||||
#define FSE_STATIC_LINKING_ONLY  /* FSE_MIN_TABLELOG */
 | 
					#define FSE_STATIC_LINKING_ONLY  /* FSE_MIN_TABLELOG */
 | 
				
			||||||
#include "fse.h"   /* FSE_isError, FSE_getErrorName */
 | 
					#include "fse.h"
 | 
				
			||||||
#define HUF_STATIC_LINKING_ONLY  /* HUF_TABLELOG_ABSOLUTEMAX */
 | 
					#define HUF_STATIC_LINKING_ONLY  /* HUF_TABLELOG_ABSOLUTEMAX */
 | 
				
			||||||
#include "huf.h"   /* HUF_isError, HUF_getErrorName */
 | 
					#include "huf.h"
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*-****************************************
 | 
					/*-****************************************
 | 
				
			||||||
@@ -90,7 +89,7 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
 | 
				
			|||||||
    threshold = 1<<nbBits;
 | 
					    threshold = 1<<nbBits;
 | 
				
			||||||
    nbBits++;
 | 
					    nbBits++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while ((remaining>1) && (charnum<=*maxSVPtr)) {
 | 
					    while ((remaining>1) & (charnum<=*maxSVPtr)) {
 | 
				
			||||||
        if (previous0) {
 | 
					        if (previous0) {
 | 
				
			||||||
            unsigned n0 = charnum;
 | 
					            unsigned n0 = charnum;
 | 
				
			||||||
            while ((bitStream & 0xFFFF) == 0xFFFF) {
 | 
					            while ((bitStream & 0xFFFF) == 0xFFFF) {
 | 
				
			||||||
@@ -115,10 +114,9 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
 | 
				
			|||||||
                ip += bitCount>>3;
 | 
					                ip += bitCount>>3;
 | 
				
			||||||
                bitCount &= 7;
 | 
					                bitCount &= 7;
 | 
				
			||||||
                bitStream = MEM_readLE32(ip) >> bitCount;
 | 
					                bitStream = MEM_readLE32(ip) >> bitCount;
 | 
				
			||||||
            }
 | 
					            } else {
 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                bitStream >>= 2;
 | 
					                bitStream >>= 2;
 | 
				
			||||||
        }
 | 
					        }   }
 | 
				
			||||||
        {   short const max = (short)((2*threshold-1)-remaining);
 | 
					        {   short const max = (short)((2*threshold-1)-remaining);
 | 
				
			||||||
            short count;
 | 
					            short count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -148,12 +146,11 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
 | 
				
			|||||||
                ip = iend - 4;
 | 
					                ip = iend - 4;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            bitStream = MEM_readLE32(ip) >> (bitCount & 31);
 | 
					            bitStream = MEM_readLE32(ip) >> (bitCount & 31);
 | 
				
			||||||
    }   }   /* while ((remaining>1) && (charnum<=*maxSVPtr)) */
 | 
					    }   }   /* while ((remaining>1) & (charnum<=*maxSVPtr)) */
 | 
				
			||||||
    if (remaining != 1) return ERROR(GENERIC);
 | 
					    if (remaining != 1) return ERROR(corruption_detected);
 | 
				
			||||||
    *maxSVPtr = charnum-1;
 | 
					    *maxSVPtr = charnum-1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ip += (bitCount+7)>>3;
 | 
					    ip += (bitCount+7)>>3;
 | 
				
			||||||
    if ((size_t)(ip-istart) > hbSize) return ERROR(srcSize_wrong);
 | 
					 | 
				
			||||||
    return ip-istart;
 | 
					    return ip-istart;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -162,7 +159,7 @@ size_t FSE_readNCount (short* normalizedCounter, unsigned* maxSVPtr, unsigned* t
 | 
				
			|||||||
    Read compact Huffman tree, saved by HUF_writeCTable().
 | 
					    Read compact Huffman tree, saved by HUF_writeCTable().
 | 
				
			||||||
    `huffWeight` is destination buffer.
 | 
					    `huffWeight` is destination buffer.
 | 
				
			||||||
    @return : size read from `src` , or an error Code .
 | 
					    @return : size read from `src` , or an error Code .
 | 
				
			||||||
    Note : Needed by HUF_readCTable() and HUF_readDTableXn() .
 | 
					    Note : Needed by HUF_readCTable() and HUF_readDTableX?() .
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
 | 
					size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
 | 
				
			||||||
                     U32* nbSymbolsPtr, U32* tableLogPtr,
 | 
					                     U32* nbSymbolsPtr, U32* tableLogPtr,
 | 
				
			||||||
@@ -176,12 +173,6 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
 | 
				
			|||||||
    /* memset(huffWeight, 0, hwSize);   *//* is not necessary, even though some analyzer complain ... */
 | 
					    /* memset(huffWeight, 0, hwSize);   *//* is not necessary, even though some analyzer complain ... */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (iSize >= 128) {  /* special header */
 | 
					    if (iSize >= 128) {  /* special header */
 | 
				
			||||||
        if (iSize >= (242)) {  /* RLE */
 | 
					 | 
				
			||||||
            static U32 l[14] = { 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128 };
 | 
					 | 
				
			||||||
            oSize = l[iSize-242];
 | 
					 | 
				
			||||||
            memset(huffWeight, 1, hwSize);
 | 
					 | 
				
			||||||
            iSize = 0;
 | 
					 | 
				
			||||||
        } else {   /* Incompressible */
 | 
					 | 
				
			||||||
        oSize = iSize - 127;
 | 
					        oSize = iSize - 127;
 | 
				
			||||||
        iSize = ((oSize+1)/2);
 | 
					        iSize = ((oSize+1)/2);
 | 
				
			||||||
        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
 | 
					        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
 | 
				
			||||||
@@ -191,7 +182,7 @@ size_t HUF_readStats(BYTE* huffWeight, size_t hwSize, U32* rankStats,
 | 
				
			|||||||
            for (n=0; n<oSize; n+=2) {
 | 
					            for (n=0; n<oSize; n+=2) {
 | 
				
			||||||
                huffWeight[n]   = ip[n/2] >> 4;
 | 
					                huffWeight[n]   = ip[n/2] >> 4;
 | 
				
			||||||
                huffWeight[n+1] = ip[n/2] & 15;
 | 
					                huffWeight[n+1] = ip[n/2] & 15;
 | 
				
			||||||
    }   }   }   }
 | 
					    }   }   }
 | 
				
			||||||
    else  {   /* header compressed with FSE (normal case) */
 | 
					    else  {   /* header compressed with FSE (normal case) */
 | 
				
			||||||
        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
 | 
					        if (iSize+1 > srcSize) return ERROR(srcSize_wrong);
 | 
				
			||||||
        oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */
 | 
					        oSize = FSE_decompress(huffWeight, hwSize-1, ip+1, iSize);   /* max (hwSize-1) values decoded, as last one is implied */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -105,68 +105,39 @@ size_t HUF_writeCTable (void* dst, size_t maxDstSize,
 | 
				
			|||||||
                        const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog)
 | 
					                        const HUF_CElt* CTable, U32 maxSymbolValue, U32 huffLog)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BYTE bitsToWeight[HUF_TABLELOG_MAX + 1];
 | 
					    BYTE bitsToWeight[HUF_TABLELOG_MAX + 1];
 | 
				
			||||||
    BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];
 | 
					    BYTE huffWeight[HUF_SYMBOLVALUE_MAX];
 | 
				
			||||||
    U32 n;
 | 
					 | 
				
			||||||
    BYTE* op = (BYTE*)dst;
 | 
					    BYTE* op = (BYTE*)dst;
 | 
				
			||||||
    size_t size;
 | 
					    U32 n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     /* check conditions */
 | 
					     /* check conditions */
 | 
				
			||||||
    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX + 1)
 | 
					    if (maxSymbolValue > HUF_SYMBOLVALUE_MAX) return ERROR(GENERIC);
 | 
				
			||||||
        return ERROR(GENERIC);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* convert to weight */
 | 
					    /* convert to weight */
 | 
				
			||||||
    bitsToWeight[0] = 0;
 | 
					    bitsToWeight[0] = 0;
 | 
				
			||||||
    for (n=1; n<=huffLog; n++)
 | 
					    for (n=1; n<huffLog+1; n++)
 | 
				
			||||||
        bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
 | 
					        bitsToWeight[n] = (BYTE)(huffLog + 1 - n);
 | 
				
			||||||
    for (n=0; n<maxSymbolValue; n++)
 | 
					    for (n=0; n<maxSymbolValue; n++)
 | 
				
			||||||
        huffWeight[n] = bitsToWeight[CTable[n].nbBits];
 | 
					        huffWeight[n] = bitsToWeight[CTable[n].nbBits];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size = FSE_compress(op+1, maxDstSize-1, huffWeight, maxSymbolValue);   /* don't need last symbol stat : implied */
 | 
					    {   size_t const size = FSE_compress(op+1, maxDstSize-1, huffWeight, maxSymbolValue);
 | 
				
			||||||
    if (HUF_isError(size)) return size;
 | 
					        if (FSE_isError(size)) return size;
 | 
				
			||||||
    if (size >= 128) return ERROR(GENERIC);   /* should never happen, since maxSymbolValue <= 255 */
 | 
					        if ((size>1) & (size < maxSymbolValue/2)) {   /* FSE compressed */
 | 
				
			||||||
    if ((size <= 1) || (size >= maxSymbolValue/2)) {
 | 
					            op[0] = (BYTE)size;
 | 
				
			||||||
        if (size==1) {  /* RLE */
 | 
					            return size+1;
 | 
				
			||||||
            /* only possible case : series of 1 (because there are at least 2) */
 | 
					    }   }
 | 
				
			||||||
            /* can only be 2^n or (2^n-1), otherwise not an huffman tree */
 | 
					
 | 
				
			||||||
            BYTE code;
 | 
					    /* raw values */
 | 
				
			||||||
            switch(maxSymbolValue)
 | 
					    if (maxSymbolValue > (256-128)) return ERROR(GENERIC);   /* should not happen */
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
            case 1: code = 0; break;
 | 
					 | 
				
			||||||
            case 2: code = 1; break;
 | 
					 | 
				
			||||||
            case 3: code = 2; break;
 | 
					 | 
				
			||||||
            case 4: code = 3; break;
 | 
					 | 
				
			||||||
            case 7: code = 4; break;
 | 
					 | 
				
			||||||
            case 8: code = 5; break;
 | 
					 | 
				
			||||||
            case 15: code = 6; break;
 | 
					 | 
				
			||||||
            case 16: code = 7; break;
 | 
					 | 
				
			||||||
            case 31: code = 8; break;
 | 
					 | 
				
			||||||
            case 32: code = 9; break;
 | 
					 | 
				
			||||||
            case 63: code = 10; break;
 | 
					 | 
				
			||||||
            case 64: code = 11; break;
 | 
					 | 
				
			||||||
            case 127: code = 12; break;
 | 
					 | 
				
			||||||
            case 128: code = 13; break;
 | 
					 | 
				
			||||||
            default : return ERROR(corruption_detected);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            op[0] = (BYTE)(255-13 + code);
 | 
					 | 
				
			||||||
            return 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
         /* Not compressible */
 | 
					 | 
				
			||||||
        if (maxSymbolValue > (241-128)) return ERROR(GENERIC);   /* not implemented (not possible with current format) */
 | 
					 | 
				
			||||||
    if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall);   /* not enough space within dst buffer */
 | 
					    if (((maxSymbolValue+1)/2) + 1 > maxDstSize) return ERROR(dstSize_tooSmall);   /* not enough space within dst buffer */
 | 
				
			||||||
        op[0] = (BYTE)(128 /*special case*/ + 0 /* Not Compressible */ + (maxSymbolValue-1));
 | 
					    op[0] = (BYTE)(128 /*special case*/ + (maxSymbolValue-1));
 | 
				
			||||||
    huffWeight[maxSymbolValue] = 0;   /* to be sure it doesn't cause issue in final combination */
 | 
					    huffWeight[maxSymbolValue] = 0;   /* to be sure it doesn't cause issue in final combination */
 | 
				
			||||||
    for (n=0; n<maxSymbolValue; n+=2)
 | 
					    for (n=0; n<maxSymbolValue; n+=2)
 | 
				
			||||||
        op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]);
 | 
					        op[(n/2)+1] = (BYTE)((huffWeight[n] << 4) + huffWeight[n+1]);
 | 
				
			||||||
    return ((maxSymbolValue+1)/2) + 1;
 | 
					    return ((maxSymbolValue+1)/2) + 1;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* normal header case */
 | 
					 | 
				
			||||||
    op[0] = (BYTE)size;
 | 
					 | 
				
			||||||
    return size+1;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, size_t srcSize)
 | 
					size_t HUF_readCTable (HUF_CElt* CTable, U32 maxSymbolValue, const void* src, size_t srcSize)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];
 | 
					    BYTE huffWeight[HUF_SYMBOLVALUE_MAX + 1];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -565,21 +565,12 @@ Therefore, `maxBits = 4` and `weight[5] = 1`.
 | 
				
			|||||||
This is a single byte value (0-255),
 | 
					This is a single byte value (0-255),
 | 
				
			||||||
which tells how to decode the list of weights.
 | 
					which tells how to decode the list of weights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- if headerByte >= 242 : this is one of 14 pre-defined weight distributions :
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| value    |242|243|244|245|246|247|248|249|250|251|252|253|254|255|
 | 
					 | 
				
			||||||
| -------- |---|---|---|---|---|---|---|---|---|---|---|---|---|---|
 | 
					 | 
				
			||||||
| Nb of 1s | 1 | 2 | 3 | 4 | 7 | 8 | 15| 16| 31| 32| 63| 64|127|128|
 | 
					 | 
				
			||||||
|Complement| 1 | 2 | 1 | 4 | 1 | 8 | 1 | 16| 1 | 32| 1 | 64| 1 |128|
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
_Note_ : complement is found by using "join to nearest power of 2" rule.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- if headerByte >= 128 : this is a direct representation,
 | 
					- if headerByte >= 128 : this is a direct representation,
 | 
				
			||||||
  where each weight is written directly as a 4 bits field (0-15).
 | 
					  where each weight is written directly as a 4 bits field (0-15).
 | 
				
			||||||
  The full representation occupies `((nbSymbols+1)/2)` bytes,
 | 
					  The full representation occupies `((nbSymbols+1)/2)` bytes,
 | 
				
			||||||
  meaning it uses a last full byte even if nbSymbols is odd.
 | 
					  meaning it uses a last full byte even if nbSymbols is odd.
 | 
				
			||||||
  `nbSymbols = headerByte - 127;`.
 | 
					  `nbSymbols = headerByte - 127;`.
 | 
				
			||||||
  Note that maximum nbSymbols is 241-127 = 114.
 | 
					  Note that maximum nbSymbols is 255-127 = 128.
 | 
				
			||||||
  A larger serie must necessarily use FSE compression.
 | 
					  A larger serie must necessarily use FSE compression.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- if headerByte < 128 :
 | 
					- if headerByte < 128 :
 | 
				
			||||||
@@ -594,20 +585,20 @@ sharing a single distribution table.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
To decode an FSE bitstream, it is necessary to know its compressed size.
 | 
					To decode an FSE bitstream, it is necessary to know its compressed size.
 | 
				
			||||||
Compressed size is provided by `headerByte`.
 | 
					Compressed size is provided by `headerByte`.
 | 
				
			||||||
It's also necessary to know its maximum decompressed size,
 | 
					It's also necessary to know its _maximum possible_ decompressed size,
 | 
				
			||||||
which is `255`, since literal values span from `0` to `255`,
 | 
					which is `255`, since literal values span from `0` to `255`,
 | 
				
			||||||
and last symbol value is not represented.
 | 
					and last symbol value is not represented.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
An FSE bitstream starts by a header, describing probabilities distribution.
 | 
					An FSE bitstream starts by a header, describing probabilities distribution.
 | 
				
			||||||
It will create a Decoding Table.
 | 
					It will create a Decoding Table.
 | 
				
			||||||
Table must be pre-allocated, which requires to support a maximum accuracy.
 | 
					Table must be pre-allocated, which requires to support a maximum accuracy.
 | 
				
			||||||
For a list of huffman weights, recommended maximum is 7 bits.
 | 
					For a list of huffman weights, maximum accuracy is 7 bits.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FSE header is [described in relevant chapter](#fse-distribution-table--condensed-format),
 | 
					FSE header is [described in relevant chapter](#fse-distribution-table--condensed-format),
 | 
				
			||||||
and so is [FSE bitstream](#bitstream).
 | 
					and so is [FSE bitstream](#bitstream).
 | 
				
			||||||
The main difference is that Huffman header compression uses 2 states,
 | 
					The main difference is that Huffman header compression uses 2 states,
 | 
				
			||||||
which share the same FSE distribution table.
 | 
					which share the same FSE distribution table.
 | 
				
			||||||
Bitstream contains only FSE symbols, there are no interleaved "raw bitfields".
 | 
					Bitstream contains only FSE symbols (no interleaved "raw bitfields").
 | 
				
			||||||
The number of symbols to decode is discovered
 | 
					The number of symbols to decode is discovered
 | 
				
			||||||
by tracking bitStream overflow condition.
 | 
					by tracking bitStream overflow condition.
 | 
				
			||||||
When both states have overflowed the bitstream, end is reached.
 | 
					When both states have overflowed the bitstream, end is reached.
 | 
				
			||||||
@@ -616,16 +607,12 @@ When both states have overflowed the bitstream, end is reached.
 | 
				
			|||||||
##### Conversion from weights to huffman prefix codes
 | 
					##### Conversion from weights to huffman prefix codes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
All present symbols shall now have a `weight` value.
 | 
					All present symbols shall now have a `weight` value.
 | 
				
			||||||
Symbols are sorted by weight.
 | 
					It is possible to transform weights into nbBits, using this formula :
 | 
				
			||||||
Symbols with a weight of zero are removed.
 | 
					 | 
				
			||||||
Within same weight, symbols keep natural order.
 | 
					 | 
				
			||||||
Starting from lowest weight,
 | 
					 | 
				
			||||||
symbols are being allocated to a `range`.
 | 
					 | 
				
			||||||
A `weight` directly represents a `range`,
 | 
					 | 
				
			||||||
following the formulae : `range = weight ? 1 << (weight-1) : 0 ;`
 | 
					 | 
				
			||||||
Similarly, it is possible to transform weights into nbBits :
 | 
					 | 
				
			||||||
`nbBits = nbBits ? maxBits + 1 - weight : 0;` .
 | 
					`nbBits = nbBits ? maxBits + 1 - weight : 0;` .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Symbols are sorted by weight. Within same weight, symbols keep natural order.
 | 
				
			||||||
 | 
					Symbols with a weight of zero are removed.
 | 
				
			||||||
 | 
					Then, starting from lowest weight, prefix codes are distributed in order.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__Example__ :
 | 
					__Example__ :
 | 
				
			||||||
Let's presume the following list of weights has been decoded :
 | 
					Let's presume the following list of weights has been decoded :
 | 
				
			||||||
@@ -640,8 +627,6 @@ it gives the following distribution :
 | 
				
			|||||||
| Literal      |  3  |  4  |  5  |  2  |  1  |   0  |
 | 
					| Literal      |  3  |  4  |  5  |  2  |  1  |   0  |
 | 
				
			||||||
| ------------ | --- | --- | --- | --- | --- | ---- |
 | 
					| ------------ | --- | --- | --- | --- | --- | ---- |
 | 
				
			||||||
| weight       |  0  |  1  |  1  |  2  |  3  |   4  |
 | 
					| weight       |  0  |  1  |  1  |  2  |  3  |   4  |
 | 
				
			||||||
| range        |  0  |  1  |  1  |  2  |  4  |   8  |
 | 
					 | 
				
			||||||
| table entries| N/A |  0  |  1  | 2-3 | 4-7 | 8-15 |
 | 
					 | 
				
			||||||
| nb bits      |  0  |  4  |  4  |  3  |  2  |   1  |
 | 
					| nb bits      |  0  |  4  |  4  |  3  |  2  |   1  |
 | 
				
			||||||
| prefix codes | N/A | 0000| 0001| 001 | 01  |   1  |
 | 
					| prefix codes | N/A | 0000| 0001| 001 | 01  |   1  |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -665,15 +650,14 @@ header only provides compressed and regenerated size of all 4 streams combined.
 | 
				
			|||||||
In order to properly decode the 4 streams,
 | 
					In order to properly decode the 4 streams,
 | 
				
			||||||
it's necessary to know the compressed and regenerated size of each stream.
 | 
					it's necessary to know the compressed and regenerated size of each stream.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Regenerated size is easiest :
 | 
					Regenerated size of each stream can be calculated by `(totalSize+3)/4`,
 | 
				
			||||||
each stream has a size of `(totalSize+3)/4`,
 | 
					except for last one, which can be up to 3 bytes smaller, to reach `totalSize`.
 | 
				
			||||||
except the last one, which is up to 3 bytes smaller, to reach `totalSize`.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Compressed size must be provided explicitly : in the 4-streams variant,
 | 
					Compressed size is provided explicitly : in the 4-streams variant,
 | 
				
			||||||
bitstreams are preceded by 3 unsigned Little Endian 16-bits values.
 | 
					bitstreams are preceded by 3 unsigned Little Endian 16-bits values.
 | 
				
			||||||
Each value represents the compressed size of one stream, in order.
 | 
					Each value represents the compressed size of one stream, in order.
 | 
				
			||||||
The last stream size is deducted from total compressed size
 | 
					The last stream size is deducted from total compressed size
 | 
				
			||||||
and from already known stream sizes :
 | 
					and from previously decoded stream sizes :
 | 
				
			||||||
`stream4CSize = totalCSize - 6 - stream1CSize - stream2CSize - stream3CSize;`
 | 
					`stream4CSize = totalCSize - 6 - stream1CSize - stream2CSize - stream3CSize;`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
##### Bitstreams read and decode
 | 
					##### Bitstreams read and decode
 | 
				
			||||||
@@ -687,7 +671,7 @@ This is detected by a final bit flag :
 | 
				
			|||||||
the highest bit of latest byte is a final-bit-flag.
 | 
					the highest bit of latest byte is a final-bit-flag.
 | 
				
			||||||
Consequently, a last byte of `0` is not possible.
 | 
					Consequently, a last byte of `0` is not possible.
 | 
				
			||||||
And the final-bit-flag itself is not part of the useful bitstream.
 | 
					And the final-bit-flag itself is not part of the useful bitstream.
 | 
				
			||||||
Hence, the last byte contain between 0 and 7 useful bits.
 | 
					Hence, the last byte contains between 0 and 7 useful bits.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Starting from the end,
 | 
					Starting from the end,
 | 
				
			||||||
it's possible to read the bitstream in a little-endian fashion,
 | 
					it's possible to read the bitstream in a little-endian fashion,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user