X-Git-Url: https://git.sesse.net/?p=fjl;a=blobdiff_plain;f=dehuff.h;h=728c62315c5570c9b3fb6f1771368d219330a2a3;hp=b79a79ace3fe976b2f38d8bf375b980b90ccafe7;hb=0b02847989970a190c2cfaec4d1abaa1f616284a;hpb=47de6c270a336574dce220cde780a802a513d113 diff --git a/dehuff.h b/dehuff.h index b79a79a..728c623 100644 --- a/dehuff.h +++ b/dehuff.h @@ -5,10 +5,14 @@ #include #include -// A function to read bytes from some input source. The bytes should be -// already unstuffed (and thus without markers). -// A return value of -1 indicates error, a return value of 0 indicates EOF. -typedef ssize_t (raw_input_func_t)(void*, uint8_t*, size_t); +#include "bytesource.h" +#include "bitsource.h" + +// About 99% of all Huffman codes are <= 8 bits long (see codelen.txt), +// and it's what libjpeg uses. Thus, it seems like a reasonable size. +#define DEHUF_TABLE_BITS 8 +#define DEHUF_TABLE_SIZE (1 << DEHUF_TABLE_BITS) +static const int DEHUF_SLOW_PATH = -1; struct huffman_table { unsigned num_codes[17]; // BITS @@ -20,6 +24,15 @@ struct huffman_table { int maxcode[16]; int mincode[16]; unsigned valptr[16]; + + // Lookup table for fast decoding; given eight bits, + // return the symbol and length in bits. For longer codes, + // DEHUF_SLOW_PATH is returned. + + // Note that the codes we return are 8-bit, but the type of + // the lookup tables is int to avoid extra zero extending. + int lookup_table_codes[DEHUF_TABLE_SIZE]; + int lookup_table_length[DEHUF_TABLE_SIZE]; }; enum coefficient_class { @@ -29,6 +42,28 @@ enum coefficient_class { }; typedef struct huffman_table huffman_tables_t[NUM_COEFF_CLASSES][4]; -void read_huffman_tables(huffman_tables_t* dst, raw_input_func_t* input_func, void* userdata); +// Read Huffman tables from a stream, and compute the derived values. +void read_huffman_tables(huffman_tables_t* dst, input_func_t* input_func, void* userdata); + +unsigned read_huffman_symbol_slow_path(const struct huffman_table* table, + struct bit_source* source); + +static inline unsigned read_huffman_symbol(const struct huffman_table* table, + struct bit_source* source) +{ + // FIXME: We can read past the end of the stream here in some edge + // cases. We need to define some guarantees in the layers above. + possibly_refill(source, DEHUF_TABLE_BITS); + unsigned lookup = peek_bits(source, DEHUF_TABLE_BITS); + int code = table->lookup_table_codes[lookup]; + int length = table->lookup_table_length[lookup]; + + if (code == DEHUF_SLOW_PATH) { + return read_huffman_symbol_slow_path(table, source); + } + + read_bits(source, length); + return code; +} #endif /* !defined(_DEHUFF_H) */