From c16ea160b709d052320236005472befce2275c37 Mon Sep 17 00:00:00 2001 From: Lee Salzman Date: Sun, 23 May 2010 06:58:05 +0000 Subject: [PATCH] range coder cleanups git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@5004 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- source/enet/compress.c | 319 +++++++++++++++++++++++------------------ source/lib/enet.lib | Bin 41120 -> 42476 bytes 2 files changed, 180 insertions(+), 139 deletions(-) diff --git a/source/enet/compress.c b/source/enet/compress.c index 07f159e0..e8726648 100644 --- a/source/enet/compress.c +++ b/source/enet/compress.c @@ -1,6 +1,6 @@ /** @file compress.c - @brief An order-1 adaptive range coder + @brief An order-2 adaptive range coder */ #define ENET_BUILDING_LIB 1 #include @@ -8,18 +8,18 @@ typedef struct _ENetSymbol { + /* binary indexed tree of symbols */ enet_uint8 value; enet_uint8 count; - enet_uint16 total; + enet_uint16 under; enet_uint16 left, right; -} ENetSymbol; -typedef struct _ENetPredictor -{ + /* context defined by this symbol */ + enet_uint16 symbols; enet_uint16 escapes; enet_uint16 total; - ENetSymbol *symbols; -} ENetPredictor; + enet_uint16 parent; +} ENetSymbol; enum { @@ -30,14 +30,15 @@ enum ENET_CONTEXT_SYMBOL_MINIMUM = 1, ENET_CONTEXT_ESCAPE_MINIMUM = 1, + ENET_SUBCONTEXT_ORDER = 2, ENET_SUBCONTEXT_SYMBOL_DELTA = 2, - ENET_SUBCONTEXT_ESCAPE_DELTA = 3 + ENET_SUBCONTEXT_ESCAPE_DELTA = 5 }; typedef struct _ENetRangeCoder { - ENetPredictor context, subcontexts[256]; - ENetSymbol symbols[256 + ENET_PROTOCOL_MAXIMUM_MTU + 1]; + /* only allocate enough symbols for reasonable MTUs */ + ENetSymbol symbols[4096]; } ENetRangeCoder; void * @@ -60,21 +61,26 @@ enet_range_coder_destroy (void * context) enet_free (rangeCoder); } -#define ENET_PREDICTOR_CREATE(predictor, escapes_, minimum) \ -{ \ - (predictor).escapes = escapes_; \ - (predictor).total = escapes_ + 256*minimum; \ - (predictor).symbols = NULL; \ -} - #define ENET_SYMBOL_CREATE(symbol, value_, count_) \ { \ symbol = & rangeCoder -> symbols [nextSymbol ++]; \ symbol -> value = value_; \ symbol -> count = count_; \ - symbol -> total = count_; \ + symbol -> under = count_; \ symbol -> left = 0; \ symbol -> right = 0; \ + symbol -> symbols = 0; \ + symbol -> escapes = 0; \ + symbol -> total = 0; \ + symbol -> parent = 0; \ +} + +#define ENET_CONTEXT_CREATE(context, escapes_, minimum) \ +{ \ + ENET_SYMBOL_CREATE (context, 0, 0); \ + (context) -> escapes = escapes_; \ + (context) -> total = escapes_ + 256*minimum; \ + (context) -> symbols = 0; \ } static enet_uint16 @@ -84,21 +90,21 @@ enet_symbol_rescale (ENetSymbol * symbol) for (;;) { symbol -> count -= symbol->count >> 1; - symbol -> total = symbol -> count; + symbol -> under = symbol -> count; if (symbol -> left) - symbol -> total += enet_symbol_rescale (symbol + symbol -> left); - total += symbol -> total; + symbol -> under += enet_symbol_rescale (symbol + symbol -> left); + total += symbol -> under; if (! symbol -> right) break; symbol += symbol -> right; } return total; } -#define ENET_PREDICTOR_RESCALE(predictor, minimum) \ +#define ENET_CONTEXT_RESCALE(context, minimum) \ { \ - (predictor).total = (predictor).symbols != NULL ? enet_symbol_rescale ((predictor).symbols) : 0; \ - (predictor).escapes -= (predictor).escapes >> 1; \ - (predictor).total += (predictor).escapes + 256*minimum; \ + (context) -> total = (context) -> symbols ? enet_symbol_rescale ((context) + (context) -> symbols) : 0; \ + (context) -> escapes -= (context) -> escapes >> 1; \ + (context) -> total += (context) -> escapes + 256*minimum; \ } #define ENET_RANGE_CODER_OUTPUT(value) \ @@ -137,48 +143,55 @@ enet_symbol_rescale (ENetSymbol * symbol) #define ENET_RANGE_CODER_FREE_SYMBOLS \ { \ - if (nextSymbol + 1 >= sizeof (rangeCoder -> symbols) / sizeof (ENetSymbol)) \ + if (nextSymbol >= sizeof (rangeCoder -> symbols) / sizeof (ENetSymbol) - ENET_SUBCONTEXT_ORDER) \ { \ - ENET_PREDICTOR_CREATE (rangeCoder -> context, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); \ - subcontext = NULL; \ nextSymbol = 0; \ + ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); \ + predicted = 0; \ + order = 0; \ } \ } -#define ENET_PREDICTOR_ENCODE(predictor, value_, under_, count_, update) \ +#define ENET_CONTEXT_ENCODE(context, symbol_, value_, under_, count_, update) \ { \ + ENetSymbol * child; \ under_ = 0; \ count_ = 0; \ - if ((predictor).symbols == NULL) \ + if (! (context) -> symbols) \ { \ - ENET_SYMBOL_CREATE ((predictor).symbols, value_, update); \ + ENET_SYMBOL_CREATE (child, value_, update); \ + (context) -> symbols = child - (context); \ + symbol_ = child; \ } \ else \ { \ - ENetSymbol * symbol = (predictor).symbols, * child; \ + ENetSymbol * node = (context) + (context) -> symbols; \ for (;;) \ { \ - if (value_ < symbol -> value) \ + if (value_ < node -> value) \ { \ - symbol -> total += update; \ - if (symbol -> left) { symbol += symbol -> left; continue; } \ + node -> under += update; \ + if (node -> left) { node += node -> left; continue; } \ ENET_SYMBOL_CREATE (child, value_, update); \ - symbol -> left = child - symbol; \ + node -> left = child - node; \ + symbol_ = child; \ } \ else \ - if (value_ > symbol -> value) \ + if (value_ > node -> value) \ { \ - under_ += symbol -> total; \ - if (symbol -> right) { symbol += symbol -> right; continue; } \ + under_ += node -> under; \ + if (node -> right) { node += node -> right; continue; } \ ENET_SYMBOL_CREATE (child, value_, update); \ - symbol -> right = child - symbol; \ + node -> right = child - node; \ + symbol_ = child; \ } \ else \ { \ - count_ = symbol -> count; \ - under_ += symbol -> total - count_; \ - symbol -> total += update; \ - symbol -> count += update; \ + count_ = node -> count; \ + under_ += node -> under - count_; \ + node -> under += update; \ + node -> count += update; \ + symbol_ = node; \ } \ break; \ } \ @@ -192,8 +205,9 @@ enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t enet_uint8 * outStart = outData, * outEnd = & outData [outLimit]; const enet_uint8 * inData, * inEnd; enet_uint32 encodeLow = 0, encodeRange = ~0; - ENetPredictor * subcontext = NULL; - size_t nextSymbol = 0; + ENetSymbol * root; + enet_uint16 predicted = 0; + size_t order = 0, nextSymbol = 0; if (rangeCoder == NULL || inBufferCount <= 0 || inLimit <= 0) return 0; @@ -203,12 +217,14 @@ enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t inBuffers ++; inBufferCount --; - ENET_PREDICTOR_CREATE (rangeCoder -> context, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); + ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); for (;;) { + ENetSymbol * subcontext, * symbol; enet_uint8 value; - enet_uint16 under, count; + enet_uint16 under, count, * parent = & predicted; + size_t level = order; if (inData >= inEnd) { if (inBufferCount <= 0) @@ -220,9 +236,13 @@ enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t } value = * inData ++; - if (subcontext != NULL) + for (subcontext = & rangeCoder -> symbols [predicted]; + subcontext != root; + subcontext = & rangeCoder -> symbols [subcontext -> parent]) { - ENET_PREDICTOR_ENCODE (* subcontext, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA); + ENET_CONTEXT_ENCODE (subcontext, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA); + * parent = symbol - rangeCoder -> symbols; + parent = & symbol -> parent; if (count > 0) { ENET_RANGE_CODER_ENCODE (subcontext -> escapes + under, count, subcontext -> total); @@ -230,29 +250,29 @@ enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t else { if (subcontext -> escapes > 0) - ENET_RANGE_CODER_ENCODE (0, subcontext -> escapes, subcontext -> total); + ENET_RANGE_CODER_ENCODE (0, subcontext -> escapes, subcontext -> total); subcontext -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA; subcontext -> total += ENET_SUBCONTEXT_ESCAPE_DELTA; } subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA; if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100) - ENET_PREDICTOR_RESCALE (* subcontext, 0); - if (count <= 0) - goto parentContext; - } - else - { - parentContext: - ENET_PREDICTOR_ENCODE (rangeCoder -> context, value, under, count, ENET_CONTEXT_SYMBOL_DELTA); - if (count <= 0) - ENET_PREDICTOR_CREATE (rangeCoder -> subcontexts [value], 0, 0); - ENET_RANGE_CODER_ENCODE (rangeCoder -> context.escapes + under + value*ENET_CONTEXT_SYMBOL_MINIMUM, count + ENET_CONTEXT_SYMBOL_MINIMUM, rangeCoder -> context.total); - rangeCoder -> context.total += ENET_CONTEXT_SYMBOL_DELTA; - if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA || rangeCoder -> context.total > ENET_RANGE_CODER_BOTTOM - 0x100) - ENET_PREDICTOR_RESCALE (rangeCoder -> context, ENET_CONTEXT_SYMBOL_MINIMUM); + ENET_CONTEXT_RESCALE (subcontext, 0); + if (count > 0) goto nextInput; } - subcontext = & rangeCoder -> subcontexts [value]; + ENET_CONTEXT_ENCODE (root, symbol, value, under, count, ENET_CONTEXT_SYMBOL_DELTA); + * parent = symbol - rangeCoder -> symbols; + parent = & symbol -> parent; + ENET_RANGE_CODER_ENCODE (root -> escapes + under + value*ENET_CONTEXT_SYMBOL_MINIMUM, count + ENET_CONTEXT_SYMBOL_MINIMUM, root -> total); + root -> total += ENET_CONTEXT_SYMBOL_DELTA; + if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100) + ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM); + + nextInput: + if (order >= ENET_SUBCONTEXT_ORDER) + predicted = rangeCoder -> symbols [predicted].parent; + else + order ++; ENET_RANGE_CODER_FREE_SYMBOLS; } @@ -290,84 +310,91 @@ enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t } \ } -#define ENET_PREDICTOR_TRY_DECODE(predictor, code, value_, under_, count_, update) \ +#define ENET_CONTEXT_TRY_DECODE(context, symbol_, code, value_, under_, count_, update) \ { \ under_ = 0; \ count_ = 0; \ - if ((predictor).symbols == NULL) \ + if (! (context) -> symbols) \ return 0; \ else \ { \ - ENetSymbol * symbol = (predictor).symbols; \ + ENetSymbol * node = (context) + (context) -> symbols; \ for (;;) \ { \ - if (code >= under_ + symbol -> total) \ + if (code >= under_ + node -> under) \ { \ - under_ += symbol -> total; \ - if (! symbol -> right) return 0; \ - symbol += symbol -> right; \ + under_ += node -> under; \ + if (! node -> right) return 0; \ + node += node -> right; \ } \ else \ - if (code < under_ + symbol -> total - symbol -> count) \ + if (code < under_ + node -> under - node -> count) \ { \ - symbol -> total += update; \ - if (! symbol -> left) return 0; \ - symbol += symbol -> left; \ + node -> under += update; \ + if (! node -> left) return 0; \ + node += node -> left; \ } \ else \ { \ - value_ = symbol -> value; \ - count_ = symbol -> count; \ - under_ += symbol -> total - count_; \ - symbol -> total += update; \ - symbol -> count += update; \ + value_ = node -> value; \ + count_ = node -> count; \ + under_ += node -> under - count_; \ + node -> under += update; \ + node -> count += update; \ + symbol_ = node; \ break; \ } \ } \ } \ } -#define ENET_PREDICTOR_DECODE(predictor, code, value_, under_, count_, update, minimum) \ +#define ENET_CONTEXT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum) \ { \ + ENetSymbol * child; \ int lowValue = -1; \ under_ = 0; \ count_ = 0; \ - if ((predictor).symbols == NULL) \ + if (! (context) -> symbols) \ { \ value_ = code / minimum; \ - ENET_SYMBOL_CREATE ((predictor).symbols, value_, update); \ + ENET_SYMBOL_CREATE (child, value_, update); \ + (context) -> symbols = child - (context); \ + symbol_ = child; \ } \ else \ { \ - ENetSymbol * symbol = (predictor).symbols, * child; \ + ENetSymbol * node = (context) + (context) -> symbols; \ for (;;) \ { \ - enet_uint16 total = under_ + symbol -> total + (symbol -> value + 1)*minimum; \ + enet_uint16 total = under_ + node -> under + (node -> value + 1)*minimum; \ if (code >= total) \ { \ - under_ += symbol -> total; \ - lowValue = symbol -> value; \ - if (symbol -> right) { symbol += symbol -> right; continue; } \ + under_ += node -> under; \ + lowValue = node -> value; \ + if (node -> right) { node += node -> right; continue; } \ value_ = lowValue + 1 + (code - under_ - (lowValue + 1)*minimum) / minimum; \ ENET_SYMBOL_CREATE (child, value_, update); \ - symbol -> right = child - symbol; \ + node -> right = child - node; \ + symbol_ = child; \ } \ else \ - if (code < total - symbol -> count - minimum) \ + if (code < total - node -> count - minimum) \ { \ - symbol -> total += update; \ - if (symbol -> left) { symbol += symbol -> left; continue; } \ + node -> under += update; \ + if (node -> left) { node += node -> left; continue; } \ value_ = lowValue + 1 + (code - under_ - (lowValue + 1)*minimum) / minimum; \ ENET_SYMBOL_CREATE (child, value_, update); \ - symbol -> left = child - symbol; \ + node -> left = child - node; \ + symbol_ = child; \ } \ else \ { \ - value_ = symbol -> value; \ - count_ = symbol -> count; \ - under_ += symbol -> total - count_; \ - symbol -> total += update; \ - symbol -> count += update; \ + value_ = node -> value; \ + count_ = node -> count; \ + under_ += node -> under - count_; \ + node -> under += update; \ + node -> count += update; \ + symbol_ = node; \ } \ break; \ } \ @@ -381,70 +408,84 @@ enet_range_coder_decompress (void * context, const enet_uint8 * inData, size_t i enet_uint8 * outStart = outData, * outEnd = & outData [outLimit]; const enet_uint8 * inEnd = & inData [inLimit]; enet_uint32 decodeLow = 0, decodeCode = 0, decodeRange = ~0; - ENetPredictor * subcontext = NULL; - size_t nextSymbol = 0; + ENetSymbol * root; + enet_uint16 predicted = 0; + size_t order = 0, nextSymbol = 0; if (rangeCoder == NULL || inLimit <= 0) return 0; - ENET_PREDICTOR_CREATE (rangeCoder -> context, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); + ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); ENET_RANGE_CODER_SEED; for (;;) { + ENetSymbol * subcontext, * symbol, * patch; enet_uint8 value = 0; - enet_uint16 code, under, count; - if (subcontext != NULL && subcontext -> escapes > 0) + enet_uint16 code, under, count, bottom, * parent = & predicted; + + for (subcontext = & rangeCoder -> symbols [predicted]; + subcontext != root; + subcontext = & rangeCoder -> symbols [subcontext -> parent]) { + if (subcontext -> escapes <= 0) + continue; code = ENET_RANGE_CODER_READ (subcontext -> total); - if (code < subcontext -> escapes) + if (code < subcontext -> escapes) { ENET_RANGE_CODER_DECODE (0, subcontext -> escapes, subcontext -> total); - goto parentContext; + continue; } code -= subcontext -> escapes; - ENET_PREDICTOR_TRY_DECODE (* subcontext, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA); + ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA); + bottom = symbol - rangeCoder -> symbols; ENET_RANGE_CODER_DECODE (subcontext -> escapes + under, count, subcontext -> total); subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA; if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100) - ENET_PREDICTOR_RESCALE (* subcontext, 0); + ENET_CONTEXT_RESCALE (subcontext, 0); + goto patchContexts; } - else + + code = ENET_RANGE_CODER_READ (root -> total); + if (code < root -> escapes) { - parentContext: - code = ENET_RANGE_CODER_READ (rangeCoder -> context.total); - if (code < rangeCoder -> context.escapes) - { - ENET_RANGE_CODER_DECODE (0, rangeCoder -> context.escapes, rangeCoder -> context.total); - break; - } - code -= rangeCoder -> context.escapes; - ENET_PREDICTOR_DECODE (rangeCoder -> context, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM); - if (count <= 0) - ENET_PREDICTOR_CREATE (rangeCoder -> subcontexts [value], 0, 0); - ENET_RANGE_CODER_DECODE (rangeCoder -> context.escapes + under + value*ENET_CONTEXT_SYMBOL_MINIMUM, count + ENET_CONTEXT_SYMBOL_MINIMUM, rangeCoder -> context.total); - rangeCoder -> context.total += ENET_CONTEXT_SYMBOL_DELTA; - if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA || rangeCoder -> context.total > ENET_RANGE_CODER_BOTTOM - 0x100) - ENET_PREDICTOR_RESCALE (rangeCoder -> context, ENET_CONTEXT_SYMBOL_MINIMUM); - if (subcontext != NULL) - { - enet_uint16 under, count; - ENET_PREDICTOR_ENCODE (* subcontext, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA); - if (count <= 0) - { - subcontext -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA; - subcontext -> total += ENET_SUBCONTEXT_ESCAPE_DELTA; - } - subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA; - if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100) - ENET_PREDICTOR_RESCALE (* subcontext, 0); - } + ENET_RANGE_CODER_DECODE (0, root -> escapes, root -> total); + break; } + code -= root -> escapes; + ENET_CONTEXT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM); + bottom = symbol - rangeCoder -> symbols; + ENET_RANGE_CODER_DECODE (root -> escapes + under + value*ENET_CONTEXT_SYMBOL_MINIMUM, count + ENET_CONTEXT_SYMBOL_MINIMUM, root -> total); + root -> total += ENET_CONTEXT_SYMBOL_DELTA; + if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100) + ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM); + + patchContexts: + for (patch = & rangeCoder -> symbols [predicted]; + patch != subcontext; + patch = & rangeCoder -> symbols [patch -> parent]) + { + ENET_CONTEXT_ENCODE (patch, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA); + * parent = symbol - rangeCoder -> symbols; + parent = & symbol -> parent; + if (count <= 0) + { + patch -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA; + patch -> total += ENET_SUBCONTEXT_ESCAPE_DELTA; + } + patch -> total += ENET_SUBCONTEXT_SYMBOL_DELTA; + if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || patch -> total > ENET_RANGE_CODER_BOTTOM - 0x100) + ENET_CONTEXT_RESCALE (patch, 0); + } + * parent = bottom; ENET_RANGE_CODER_OUTPUT (value); - subcontext = & rangeCoder -> subcontexts [value]; + if (order >= ENET_SUBCONTEXT_ORDER) + predicted = rangeCoder -> symbols [predicted].parent; + else + order ++; ENET_RANGE_CODER_FREE_SYMBOLS; } diff --git a/source/lib/enet.lib b/source/lib/enet.lib index 65685195995c41e95f662dcc1ccc22ed5ca4fea4..20f8c516bf63c8cd74905c1a364e97a6319728aa 100644 GIT binary patch delta 6182 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 J>JR;s{Rfc+<+T6+