| #ifndef __RLE_H |
| #define __RLE_H |
| |
| #include <string.h> |
| #include <assert.h> |
| #include "mem.h" |
| #include "bitcoder.h" |
| #include "golomb.h" |
| |
| #if defined(RLECODER) |
| |
| #define OUTPUT_BIT(rlecoder,bit) rlecoder_write_bit(rlecoder,bit) |
| #define INPUT_BIT(rlecoder) rlecoder_read_bit(rlecoder) |
| #define OUTPUT_BIT_DIRECT(coder,bit) bitcoder_write_bit(&(coder)->bitcoder,bit) |
| #define INPUT_BIT_DIRECT(rlecoder) bitcoder_read_bit(&(rlecoder)->bitcoder) |
| #define ENTROPY_CODER RLECoderState |
| #define ENTROPY_ENCODER_INIT(coder,limit) rlecoder_encoder_init(coder,limit) |
| #define ENTROPY_ENCODER_DONE(coder) rlecoder_encoder_done(coder) |
| #define ENTROPY_ENCODER_FLUSH(coder) rlecoder_encoder_flush(coder) |
| #define ENTROPY_DECODER_INIT(coder,bitstream,limit) \ |
| rlecoder_decoder_init(coder,bitstream,limit) |
| #define ENTROPY_DECODER_DONE(coder) /* nothing to do ... */ |
| #define ENTROPY_CODER_BITSTREAM(coder) ((coder)->bitcoder.bitstream) |
| #define ENTROPY_CODER_EOS(coder) ((coder)->bitcoder.eos) |
| |
| #define ENTROPY_CODER_SYMBOL(coder) ((coder)->symbol) |
| #define ENTROPY_CODER_RUNLENGTH(coder) ((coder)->count) |
| #define ENTROPY_CODER_SKIP(coder,skip) do { (coder)->count -= skip; } while (0) |
| #endif |
| |
| |
| |
| |
| typedef struct { |
| int symbol; |
| uint32_t count; /* have seen count symbol's */ |
| BitCoderState bitcoder; |
| GolombAdaptiveCoderState golomb_state [2]; /* 2 states for 2 symbols... */ |
| int have_seen_1; |
| } RLECoderState; |
| |
| |
| |
| /* |
| * bit should be 0 or 1 !!! |
| */ |
| static inline |
| void rlecoder_write_bit (RLECoderState *s, int bit) |
| { |
| assert (bit == 0 || bit == 1); |
| |
| if (s->symbol == -1) { |
| s->symbol = bit & 1; |
| s->count = 1; |
| s->have_seen_1 = bit; |
| bitcoder_write_bit (&s->bitcoder, bit); |
| } |
| |
| if (s->symbol != bit) { |
| golombcoder_encode_number (&s->golomb_state[s->symbol], |
| &s->bitcoder, s->count); |
| s->symbol = ~s->symbol & 1; |
| s->have_seen_1 = 1; |
| s->count = 1; |
| } else |
| s->count++; |
| } |
| |
| static inline |
| int rlecoder_read_bit (RLECoderState *s) |
| { |
| if (s->count == 0) { |
| s->symbol = ~s->symbol & 1; |
| s->count = golombcoder_decode_number (&s->golomb_state[s->symbol], |
| &s->bitcoder); |
| if (s->bitcoder.eos) { |
| s->symbol = 0; |
| s->count = ~0; |
| } |
| } |
| s->count--; |
| return (s->symbol); |
| } |
| |
| |
| int coder_id = 0; |
| FILE *file = NULL; |
| |
| static inline |
| void rlecoder_encoder_init (RLECoderState *s, uint32_t limit) |
| { |
| bitcoder_encoder_init (&s->bitcoder, limit); |
| s->symbol = -1; |
| s->have_seen_1 = 0; |
| s->golomb_state[0].count = 0; |
| s->golomb_state[1].count = 0; |
| s->golomb_state[0].bits = 5 << 3; |
| s->golomb_state[1].bits = 5 << 3; |
| } |
| |
| |
| /** |
| * once you called this, you better should not encode any more symbols ... |
| */ |
| static inline |
| uint32_t rlecoder_encoder_flush (RLECoderState *s) |
| { |
| if (s->symbol == -1 || !s->have_seen_1) |
| return 0; |
| |
| golombcoder_encode_number (&s->golomb_state[s->symbol], |
| &s->bitcoder, s->count); |
| return bitcoder_flush (&s->bitcoder); |
| } |
| |
| |
| static inline |
| void rlecoder_decoder_init (RLECoderState *s, uint8_t *bitstream, uint32_t limit) |
| { |
| bitcoder_decoder_init (&s->bitcoder, bitstream, limit); |
| s->golomb_state[0].count = 0; |
| s->golomb_state[1].count = 0; |
| s->golomb_state[0].bits = 5 << 3; |
| s->golomb_state[1].bits = 5 << 3; |
| s->symbol = bitcoder_read_bit (&s->bitcoder); |
| s->count = golombcoder_decode_number (&s->golomb_state[s->symbol], |
| &s->bitcoder) - 1; |
| if (s->bitcoder.eos) { |
| s->symbol = 0; |
| s->count = ~0; |
| } |
| } |
| |
| |
| static inline |
| void rlecoder_encoder_done (RLECoderState *s) |
| { |
| bitcoder_encoder_done (&s->bitcoder); |
| } |
| |
| |
| #endif |
| |