X-Git-Url: https://git.sesse.net/?p=fjl;a=blobdiff_plain;f=dehuff.h;h=6865dae0d7169bbe62b390e86c662d8c6439b13a;hp=b79a79ace3fe976b2f38d8bf375b980b90ccafe7;hb=4ccaf2a2ac9f78dcaaa1ba4a093b1ece3f915c94;hpb=47de6c270a336574dce220cde780a802a513d113 diff --git a/dehuff.h b/dehuff.h index b79a79a..6865dae 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 "input.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,30 @@ enum coefficient_class { }; typedef struct huffman_table huffman_tables_t[NUM_COEFF_CLASSES][4]; +// Read Huffman tables from a stream, and compute the derived values. void read_huffman_tables(huffman_tables_t* dst, raw_input_func_t* input_func, void* userdata); +unsigned read_huffman_symbol_slow_path(const struct huffman_table* table, + struct bit_source* source); + +#include + +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) */