Commit 214be50c authored by Mathis Rosenhauer's avatar Mathis Rosenhauer

encoder and encode/decode test

parent 8fe7d87e
CC = gcc
CFLAGS = -g -Wall
objects = mytest.o aed.o
OBJS = aee.o aed.o
mytest: $(objects)
$(CC) $(CFLAGS) -o mytest $(objects)
.PHONY : all clean test
aed.o: aecd.h
all: libae.a test
.PHONY : clean test vtest
clean:
rm -f mytest ../data/ae_out $(objects)
test_encode: test_encode.o libae.a
$(CC) $(CFLAGS) -o test_encode test_encode.o -L. -lae
test_decode: test_decode.o libae.a
$(CC) $(CFLAGS) -o test_decode test_decode.o -L. -lae
libae.a: $(OBJS)
$(AR) $(ARFLAGS) $@ $(OBJS)
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
test: mytest
./mytest 1 1 < ../data/example_data.szip > ../data/ae_out
diff ../data/ae_out ../data/example_data
./mytest 9478 16384 < ../data/example_data.szip > ../data/ae_out
diff ../data/ae_out ../data/example_data
aed.o: libae.h
aee.o: libae.h
clean:
rm -f $(OBJS) test_encode.o test_decode.o \
test_encode test_decode libae.a \
../data/test.ae ../data/test
vtest: mytest
valgrind -v ./mytest < ../data/example_data.szip > ../data/ae_out
diff ../data/ae_out ../data/example_data
test: test_encode test_decode
./test_encode 1 1 < ../data/example_data > ../data/test.ae
./test_decode 1 1 < ../data/test.ae > ../data/test
diff ../data/test ../data/example_data
......@@ -7,16 +7,16 @@
#include <inttypes.h>
#include <string.h>
#include "aecd.h"
#include "libae.h"
#define REFBLOCK (strm->pp && (strm->total_out / strm->block_size) \
% strm->segment_size == 0)
#define SAFE (strm->avail_in >= state->in_blklen \
&& strm->avail_out >= strm->block_size)
#define ROS 5
typedef struct internal_state {
const uint8_t *next_in;
uint32_t *next_out;
int id; /* option ID */
uint32_t id_len; /* bit length of code option identification key */
int *id_table; /* table maps IDs to states */
......@@ -33,6 +33,7 @@ typedef struct internal_state {
uint64_t acc; /* accumulator for currently used bit sequence */
uint8_t bitp; /* bit pointer to the next unused bit in accumulator */
uint32_t fs; /* last fundamental sequence in accumulator */
int ref; /* 1 if current block has reference sample */
} decode_state;
/* decoding table for the second-extension option */
......@@ -97,7 +98,7 @@ static inline void u_put(ae_streamp strm, uint32_t sample)
}
sample = x + D;
}
*strm->next_out++ = state->last_out = sample;
*state->next_out++ = state->last_out = sample;
strm->avail_out--;
strm->total_out++;
}
......@@ -117,7 +118,7 @@ static inline uint32_t u_get(ae_streamp strm, unsigned int n)
{
strm->avail_in--;
strm->total_in++;
state->acc = (state->acc << 8) + *strm->next_in++;
state->acc = (state->acc << 8) + *state->next_in++;
state->bitp += 8;
}
state->bitp -= n;
......@@ -143,25 +144,23 @@ static inline uint32_t u_get_fs(ae_streamp strm)
static inline void fast_split(ae_streamp strm)
{
int i, start, k;
int i, k;
decode_state *state;
state = strm->state;
start = 0;
k = state->id - 1;
if (REFBLOCK)
if (state->ref)
{
start = 1;
u_put(strm, u_get(strm, strm->bit_per_sample));
}
for (i = start; i < strm->block_size; i++)
for (i = state->ref; i < strm->block_size; i++)
{
state->block[i] = u_get_fs(strm) << k;
}
for (i = start; i < strm->block_size; i++)
for (i = state->ref; i < strm->block_size; i++)
{
state->block[i] += u_get(strm, k);
u_put(strm, state->block[i]);
......@@ -181,7 +180,7 @@ static inline void fast_se(ae_streamp strm)
int i;
uint32_t gamma, beta, ms, delta1;
i = REFBLOCK? 1: 0;
i = strm->state->ref;
while (i < strm->bit_per_sample)
{
......@@ -266,17 +265,17 @@ int ae_decode_init(ae_streamp strm)
return AE_OK;
}
#define ASK(n) \
do { \
while (state->bitp < (unsigned)(n)) \
{ \
if (strm->avail_in == 0) goto req_buffer; \
strm->avail_in--; \
strm->total_in++; \
state->acc <<= 8; \
state->acc |= (uint64_t)(*strm->next_in++); \
state->bitp += 8; \
} \
#define ASK(n) \
do { \
while (state->bitp < (unsigned)(n)) \
{ \
if (strm->avail_in == 0) goto req_buffer; \
strm->avail_in--; \
strm->total_in++; \
state->acc <<= 8; \
state->acc |= (uint64_t)(*state->next_in++); \
state->bitp += 8; \
} \
} while (0)
#define GET(n) \
......@@ -322,8 +321,6 @@ int ae_decode(ae_streamp strm, int flush)
Can work with one byte input und one sample output buffers. If
enough buffer space is available, then faster implementations
of the states are called. Inspired by zlib.
TODO: Flush modes like in zlib
*/
size_t zero_blocks;
......@@ -332,15 +329,23 @@ int ae_decode(ae_streamp strm, int flush)
decode_state *state;
state = strm->state;
state->next_in = strm->next_in;
state->next_out = strm->next_out;
for (;;)
{
switch(state->mode)
{
case M_ID:
ASK(3);
state->id = GET(3);
DROP(3);
if (strm->pp
&& (strm->total_out / strm->block_size) % strm->segment_size == 0)
state->ref = 1;
else
state->ref = 0;
ASK(state->id_len);
state->id = GET(state->id_len);
DROP(state->id_len);
state->mode = state->id_table[state->id];
break;
......@@ -352,7 +357,7 @@ int ae_decode(ae_streamp strm, int flush)
break;
}
if (REFBLOCK)
if (state->ref)
{
COPYSAMPLE();
state->n = strm->block_size - 1;
......@@ -366,11 +371,10 @@ int ae_decode(ae_streamp strm, int flush)
state->mode = M_SPLIT_FS;
case M_SPLIT_FS:
k = state->id - 1;
do
{
ASKFS();
state->block[state->i] = GETFS() << k;
state->block[state->i] = GETFS();
DROPFS();
}
while(--state->i);
......@@ -383,7 +387,7 @@ int ae_decode(ae_streamp strm, int flush)
do
{
ASK(k);
PUT(state->block[state->i] + GET(k));
PUT((state->block[state->i] << k) + GET(k));
DROP(k);
}
while(--state->i);
......@@ -398,7 +402,7 @@ int ae_decode(ae_streamp strm, int flush)
state->mode = M_LOW_ENTROPY_REF;
case M_LOW_ENTROPY_REF:
if (REFBLOCK)
if (state->ref)
COPYSAMPLE();
if(state->id == 1)
......@@ -422,7 +426,7 @@ int ae_decode(ae_streamp strm, int flush)
}
if (REFBLOCK)
if (state->ref)
state->i = zero_blocks * strm->block_size - 1;
else
state->i = zero_blocks * strm->block_size;
......@@ -453,7 +457,7 @@ int ae_decode(ae_streamp strm, int flush)
}
state->mode = M_SE_DECODE;
state->i = REFBLOCK? 1: 0;
state->i = state->ref;
case M_SE_DECODE:
while(state->i < strm->bit_per_sample)
......@@ -503,5 +507,7 @@ int ae_decode(ae_streamp strm, int flush)
}
req_buffer:
strm->next_in = state->next_in;
strm->next_out = state->next_out;
return AE_OK;
}
This diff is collapsed.
#ifndef AELIB_H
#define AELIB_H
#ifndef LIBAE_H
#define LIBAE_H
#include <inttypes.h>
......@@ -7,11 +7,11 @@ struct internal_state;
typedef struct _ae_stream
{
const uint8_t *next_in;
const void *next_in;
size_t avail_in; /* number of bytes available at next_in */
size_t total_in; /* total number of input bytes read so far */
uint32_t *next_out;
void *next_out;
size_t avail_out; /* remaining free space at next_out */
size_t total_out; /* total number of bytes output so far */
......@@ -34,15 +34,12 @@ typedef ae_stream *ae_streamp;
#define AE_MEM_ERROR (-4)
#define AE_NO_FLUSH 0
#define AE_PARTIAL_FLUSH 1
#define AE_SYNC_FLUSH 2
#define AE_FULL_FLUSH 3
#define AE_FINISH 4
#define AE_BLOCK 5
#define AE_TREES 6
#define AE_FLUSH 1
int ae_decode_init(ae_streamp strm);
int ae_decode(ae_streamp strm, int flush);
#endif /* AELIB_H */
int ae_encode_init(ae_streamp strm);
int ae_encode(ae_streamp strm, int flush);
#endif /* LIBAE_H */
......@@ -2,44 +2,35 @@
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include "aecd.h"
#include "libae.h"
#define CHUNK_OUT 1
#define CHUNK_IN 1
#define ALL_IN 9478
int main(int argc, char *argv[])
{
ae_stream strm;
int c, i, n, status, todo;
uint8_t *in;
uint32_t *out;
size_t total_out;
int chunk_in, chunk_out;
chunk_in = CHUNK_IN;
chunk_out = CHUNK_OUT;
int chunk_in, chunk_out, i, c, total_out, status;
int input_avail, output_avail;
if (argc == 3)
{
chunk_in = atoi(argv[1]);
chunk_out = atoi(argv[2]);
}
else
{
chunk_in = CHUNK_IN;
chunk_out = CHUNK_OUT;
}
fprintf(stderr, "chunk_in: %i\nchunk_out: %i\n", chunk_in, chunk_out);
in = (uint8_t *)malloc(ALL_IN);
in = (uint8_t *)malloc(chunk_in);
out = (uint32_t *)malloc(chunk_out * sizeof(uint32_t));
if (in == NULL || out == NULL)
return 1;
n = 0;
while ((c = getc(stdin)) != EOF)
{
*in++ = c;
n++;
}
in -= n;
strm.bit_per_sample = 8;
strm.block_size = 8;
strm.segment_size = 2;
......@@ -48,33 +39,32 @@ int main(int argc, char *argv[])
if (ae_decode_init(&strm) != AE_OK)
return 1;
strm.next_in = in;
strm.avail_in = chunk_in;
strm.next_out = out;
strm.avail_out = chunk_out;
todo = 1;
total_out = 0;
strm.avail_in = 0;
strm.avail_out = chunk_out;
strm.next_out = out;
input_avail = 1;
output_avail = 1;
while(todo)
while(input_avail || output_avail)
{
todo = 0;
if ((status = ae_decode(&strm, 0)) != AE_OK)
if (strm.avail_in == 0)
{
fprintf(stderr, "error is %i\n", status);
return 1;
i = 0;
while(i < chunk_in && (c = getc(stdin)) != EOF)
in[i++] = c;
strm.avail_in = i;
strm.next_in = in;
if (c == EOF)
input_avail = 0;
}
// fprintf(stderr, "avail in %li total in %li avail out %li total out %lx\n", strm.avail_in, strm.total_in, strm.avail_out, strm.total_out);
if (strm.avail_in == 0 && strm.total_in < ALL_IN)
if ((status = ae_decode(&strm, AE_NO_FLUSH)) != AE_OK)
{
in += chunk_in;
strm.next_in = in;
if (ALL_IN - strm.total_in < chunk_in)
strm.avail_in = ALL_IN - strm.total_in;
else
strm.avail_in = chunk_in;
todo = 1;
fprintf(stderr, "error is %i\n", status);
return 1;
}
if (strm.total_out - total_out > 0)
......@@ -84,10 +74,15 @@ int main(int argc, char *argv[])
putc(out[i], stdout);
}
total_out = strm.total_out;
output_avail = 1;
strm.next_out = out;
strm.avail_out = chunk_out;
todo = 1;
}
else
{
output_avail = 0;
}
}
return 0;
......
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <inttypes.h>
#include "libae.h"
#define CHUNK_OUT 0x4000
#define CHUNK_IN 1024
#define ALL_IN 9478
int main(int argc, char *argv[])
{
ae_stream strm;
uint32_t *in;
uint8_t *out;
int chunk_in, chunk_out, i, c, total_out, status;
int input_avail, output_avail;
if (argc == 3)
{
chunk_in = atoi(argv[1]);
chunk_out = atoi(argv[2]);
}
else
{
chunk_in = CHUNK_IN;
chunk_out = CHUNK_OUT;
}
out = (uint8_t *)malloc(chunk_out);
in = (uint32_t *)malloc(chunk_in * sizeof(uint32_t));
if (in == NULL || out == NULL)
return 1;
strm.bit_per_sample = 8;
strm.block_size = 8;
strm.segment_size = 2;
strm.pp = 1;
if (ae_encode_init(&strm) != AE_OK)
return 1;
total_out = 0;
strm.avail_in = 0;
strm.avail_out = chunk_out;
strm.next_out = out;
input_avail = 1;
output_avail = 1;
while(input_avail || output_avail)
{
if (strm.avail_in == 0)
{
i = 0;
while(i < chunk_in && (c = getc(stdin)) != EOF)
in[i++] = c;
strm.avail_in = i;
strm.next_in = in;
if (c == EOF)
input_avail = 0;
}
if ((status = ae_encode(&strm, AE_NO_FLUSH)) != AE_OK)
{
fprintf(stderr, "error is %i\n", status);
return 1;
}
if (strm.total_out - total_out > 0)
{
for (i=0; i < strm.total_out - total_out; i++)
{
putc(out[i], stdout);
}
total_out = strm.total_out;
output_avail = 1;
strm.next_out = out;
strm.avail_out = chunk_out;
}
else
{
output_avail = 0;
}
}
if ((status = ae_encode(&strm, AE_FLUSH)) != AE_OK)
{
fprintf(stderr, "error is %i\n", status);
return 1;
}
if (strm.total_out - total_out > 0)
{
for (i=0; i < strm.total_out - total_out; i++)
{
putc(out[i], stdout);
}
}
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment