decode.c 17 KB
Newer Older
1 2 3
/* Adaptive Entropy Decoder            */
/* CCSDS 121.0-B-1 and CCSDS 120.0-G-2 */

4 5 6 7 8 9
#include <config.h>

#if HAVE_STDINT_H
# include <stdint.h>
#endif

10 11 12 13 14
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
15
#include "libaec.h"
16

17 18
#define MIN(a, b) (((a) < (b))? (a): (b))

19
#define SAFE (strm->avail_in >= state->in_blklen        \
20
              && strm->avail_out >= state->out_blklen)
21 22 23 24

#define ROS 5

typedef struct internal_state {
25
    int id;            /* option ID */
26
    int id_len;        /* bit length of code option identification key */
27
    int *id_table;     /* table maps IDs to states */
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
28
    void (*put_sample)(struct aec_stream *, int64_t);
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
29
    int ref_int;       /* reference sample is every ref_int samples */
30
    int64_t last_out;  /* previous output for post-processing */
31 32 33
    int64_t xmin;      /* minimum integer for post-processing */
    int64_t xmax;      /* maximum integer for post-processing */
    int mode;          /* current mode of FSM */
34
    int in_blklen;     /* length of uncompressed input block
35
                          should be the longest possible block */
36
    int out_blklen;    /* length of output block in bytes */
37 38
    int n, i;          /* counter for samples */
    int64_t *block;    /* block buffer for split-sample options */
39 40
    int se;            /* set if second extension option is selected */
    uint64_t acc;      /* accumulator for currently used bit sequence */
41 42
    int bitp;          /* bit pointer to the next unused bit in accumulator */
    int fs;            /* last fundamental sequence in accumulator */
43
    int ref;           /* 1 if current block has reference sample */
44
    int pp;            /* 1 if postprocessor has to be used */
45
    int byte_per_sample;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
46
    size_t samples_out;
47 48 49
} decode_state;

/* decoding table for the second-extension option */
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
50
static const int second_extension[92][2] = {
51 52 53 54 55 56 57
    {0, 0},
    {1, 1}, {1, 1},
    {2, 3}, {2, 3}, {2, 3},
    {3, 6}, {3, 6}, {3, 6}, {3, 6},
    {4, 10}, {4, 10}, {4, 10}, {4, 10}, {4, 10},
    {5, 15}, {5, 15}, {5, 15}, {5, 15}, {5, 15}, {5, 15},
    {6, 21}, {6, 21}, {6, 21}, {6, 21}, {6, 21}, {6, 21}, {6, 21},
58 59 60 61 62 63
    {7, 28}, {7, 28}, {7, 28}, {7, 28}, {7, 28}, {7, 28}, {7, 28}, {7, 28},
    {8, 36}, {8, 36}, {8, 36}, {8, 36}, {8, 36}, {8, 36}, {8, 36}, {8, 36}, {8, 36},
    {9, 45}, {9, 45}, {9, 45}, {9, 45}, {9, 45}, {9, 45}, {9, 45}, {9, 45}, {9, 45}, {9, 45},
    {10, 55}, {10, 55}, {10, 55}, {10, 55}, {10, 55}, {10, 55}, {10, 55}, {10, 55}, {10, 55}, {10, 55}, {10, 55},
    {11, 66}, {11, 66}, {11, 66}, {11, 66}, {11, 66}, {11, 66}, {11, 66}, {11, 66}, {11, 66}, {11, 66}, {11, 66}, {11, 66},
    {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}, {12, 78}
64 65
};

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
66
enum {
67 68 69 70 71 72 73 74 75 76 77 78
    M_ID = 0,
    M_SPLIT,
    M_SPLIT_FS,
    M_SPLIT_OUTPUT,
    M_LOW_ENTROPY,
    M_LOW_ENTROPY_REF,
    M_ZERO_BLOCK,
    M_ZERO_OUTPUT,
    M_SE,
    M_SE_DECODE,
    M_UNCOMP,
    M_UNCOMP_COPY,
79 80
};

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
81
static void put_msb_32(struct aec_stream *strm, int64_t data)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
82 83 84 85 86 87 88 89 90
{
    *strm->next_out++ = data >> 24;
    *strm->next_out++ = data >> 16;
    *strm->next_out++ = data >> 8;
    *strm->next_out++ = data;
    strm->avail_out -= 4;
    strm->total_out += 4;
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
91
static void put_msb_24(struct aec_stream *strm, int64_t data)
92 93 94 95 96 97 98 99
{
    *strm->next_out++ = data >> 16;
    *strm->next_out++ = data >> 8;
    *strm->next_out++ = data;
    strm->avail_out -= 3;
    strm->total_out += 3;
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
100
static void put_msb_16(struct aec_stream *strm, int64_t data)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
101 102 103 104 105 106 107
{
    *strm->next_out++ = data >> 8;
    *strm->next_out++ = data;
    strm->avail_out -= 2;
    strm->total_out += 2;
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
108
static void put_lsb_32(struct aec_stream *strm, int64_t data)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
109 110 111 112 113 114 115 116 117
{
    *strm->next_out++ = data;
    *strm->next_out++ = data >> 8;
    *strm->next_out++ = data >> 16;
    *strm->next_out++ = data >> 24;
    strm->avail_out -= 4;
    strm->total_out += 4;
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
118
static void put_lsb_24(struct aec_stream *strm, int64_t data)
119 120 121 122 123 124 125 126
{
    *strm->next_out++ = data;
    *strm->next_out++ = data >> 8;
    *strm->next_out++ = data >> 16;
    strm->avail_out -= 3;
    strm->total_out += 3;
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
127
static void put_lsb_16(struct aec_stream *strm, int64_t data)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
128 129 130 131 132 133
{
    *strm->next_out++ = data;
    *strm->next_out++ = data >> 8;
    strm->avail_out -= 2;
    strm->total_out += 2;
}
134

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
135
static void put_8(struct aec_stream *strm, int64_t data)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
136 137 138 139 140
{
    *strm->next_out++ = data;
    strm->avail_out--;
    strm->total_out++;
}
141

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
142
static inline void u_put(struct aec_stream *strm, int64_t sample)
143
{
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
144 145
    int64_t x, d, th, D, lower;
    decode_state *state = strm->state;
146

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
147
    if (state->pp && (state->samples_out % state->ref_int != 0)) {
148 149
        d = sample;
        x = state->last_out;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
150 151
        lower = x - state->xmin;
        th = MIN(lower, state->xmax - x);
152

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
153
        if (d <= 2 * th) {
154 155 156 157 158
            if (d & 1)
                D = - (d + 1) / 2;
            else
                D = d / 2;
        } else {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
159
            if (th == lower)
160 161 162 163 164
                D = d - th;
            else
                D = th - d;
        }
        sample = x + D;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
165 166
    } else {
        if (strm->flags & AEC_DATA_SIGNED) {
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
167 168 169 170 171
            int m = 64 - strm->bit_per_sample;
            /* Reference samples have to be sign extended */
            sample = (sample << m) >> m;
        }
    }
172 173
    state->last_out = sample;
    state->put_sample(strm, sample);
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
174
    state->samples_out++;
175 176
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
177
static inline int64_t u_get(struct aec_stream *strm, unsigned int n)
178 179 180 181 182 183 184 185 186 187
{
    /**
       Unsafe get n bit from input stream

       No checking whatsoever. Read bits are dumped.
     */

    decode_state *state;

    state = strm->state;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
188
    while (state->bitp < n) {
189 190
        strm->avail_in--;
        strm->total_in++;
191
        state->acc = (state->acc << 8) | *strm->next_in++;
192 193 194 195 196 197
        state->bitp += 8;
    }
    state->bitp -= n;
    return (state->acc >> state->bitp) & ((1ULL << n) - 1);
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
198
static inline int64_t u_get_fs(struct aec_stream *strm)
199 200 201 202 203 204 205 206
{
    /**
       Interpret a Fundamental Sequence from the input buffer.

       Essentially counts the number of 0 bits until a
       1 is encountered. TODO: faster version.
     */

207
    int64_t fs = 0;
208 209 210 211 212 213 214

    while(u_get(strm, 1) == 0)
        fs++;

    return fs;
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
215
static inline void fast_split(struct aec_stream *strm)
216
{
217
    int i, k;
218 219 220 221 222
    decode_state *state;

    state = strm->state;
    k = state->id - 1;

223
    if (state->ref)
224
        u_put(strm, u_get(strm, strm->bit_per_sample));
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
225

226
    for (i = state->ref; i < strm->block_size; i++)
227 228
        state->block[i] = u_get_fs(strm) << k;

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
229
    for (i = state->ref; i < strm->block_size; i++) {
230 231 232 233 234
        state->block[i] += u_get(strm, k);
        u_put(strm, state->block[i]);
    }
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
235
static inline void fast_zero(struct aec_stream *strm)
236 237 238 239 240 241 242
{
    int i = strm->state->i;

    while (i--)
        u_put(strm, 0);
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
243
static inline void fast_se(struct aec_stream *strm)
244 245
{
    int i;
246
    int64_t gamma, beta, ms, delta1;
247

248
    i = strm->state->ref;
249

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
250
    while (i < strm->block_size) {
251 252 253 254
        gamma = u_get_fs(strm);
        beta = second_extension[gamma][0];
        ms = second_extension[gamma][1];
        delta1 = gamma - ms;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
255

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
256
        if ((i & 1) == 0) {
257 258 259 260 261 262 263 264
            u_put(strm, beta - delta1);
            i++;
        }
        u_put(strm, delta1);
        i++;
    }
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
265
static inline void fast_uncomp(struct aec_stream *strm)
266 267 268 269 270
{
    int i;

    for (i = 0; i < strm->block_size; i++)
        u_put(strm, u_get(strm, strm->bit_per_sample));
271 272
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
273
int aec_decode_init(struct aec_stream *strm)
274
{
275 276 277 278
    int i, modi;
    decode_state *state;

    if (strm->bit_per_sample > 32 || strm->bit_per_sample == 0)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
279
        return AEC_CONF_ERROR;
280 281 282

    state = (decode_state *) malloc(sizeof(decode_state));
    if (state == NULL)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
283
        return AEC_MEM_ERROR;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
284

285 286
    strm->state = state;

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
287
    if (strm->bit_per_sample > 16) {
288
        state->id_len = 5;
289

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
290
        if (strm->bit_per_sample <= 24 && strm->flags & AEC_DATA_3BYTE) {
291
            state->byte_per_sample = 3;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
292
            if (strm->flags & AEC_DATA_MSB)
293 294 295
                state->put_sample = put_msb_24;
            else
                state->put_sample = put_lsb_24;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
296
        } else {
297
            state->byte_per_sample = 4;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
298
            if (strm->flags & AEC_DATA_MSB)
299 300 301 302 303 304
                state->put_sample = put_msb_32;
            else
                state->put_sample = put_lsb_32;
        }
        state->out_blklen = strm->block_size
            * state->byte_per_sample;
305
    }
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
306
    else if (strm->bit_per_sample > 8) {
307
        state->byte_per_sample = 2;
308
        state->id_len = 4;
309
        state->out_blklen = strm->block_size * 2;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
310
        if (strm->flags & AEC_DATA_MSB)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
311
            state->put_sample = put_msb_16;
312
        else
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
313
            state->put_sample = put_lsb_16;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
314
    } else {
315
        state->byte_per_sample = 1;
316
        state->id_len = 3;
317
        state->out_blklen = strm->block_size;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
318
        state->put_sample = put_8;
319 320
    }

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
321
    if (strm->flags & AEC_DATA_SIGNED) {
322 323
        state->xmin = -(1ULL << (strm->bit_per_sample - 1));
        state->xmax = (1ULL << (strm->bit_per_sample - 1)) - 1;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
324
    } else {
325 326 327
        state->xmin = 0;
        state->xmax = (1ULL << strm->bit_per_sample) - 1;
    }
328

329
    state->ref_int = strm->block_size * strm->rsi;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
330
    state->in_blklen = (strm->block_size * strm->bit_per_sample
331 332 333 334 335
                        + state->id_len) / 8 + 1;

    modi = 1UL << state->id_len;
    state->id_table = (int *)malloc(modi * sizeof(int));
    if (state->id_table == NULL)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
336
        return AEC_MEM_ERROR;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
337

338
    state->id_table[0] = M_LOW_ENTROPY;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
339
    for (i = 1; i < modi - 1; i++) {
340 341 342 343
        state->id_table[i] = M_SPLIT;
    }
    state->id_table[modi - 1] = M_UNCOMP;

344
    state->block = (int64_t *)malloc(strm->block_size * sizeof(int64_t));
345
    if (state->block == NULL)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
346
        return AEC_MEM_ERROR;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
347

348 349 350
    strm->total_in = 0;
    strm->total_out = 0;

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
351
    state->samples_out = 0;
352
    state->bitp = 0;
353
    state->fs = 0;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
354
    state->pp = strm->flags & AEC_DATA_PREPROCESS;
355
    state->mode = M_ID;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
356
    return AEC_OK;
357 358
}

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
359
int aec_decode_end(struct aec_stream *strm)
360 361 362 363 364 365 366
{
    decode_state *state;

    state = strm->state;
    free(state->block);
    free(state->id_table);
    free(state);
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
367
    return AEC_OK;
368 369
}

370 371
#define ASK(n)                                           \
    do {                                                 \
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
372 373 374
        while (state->bitp < (unsigned)(n)) {            \
            if (strm->avail_in == 0)                     \
                goto req_buffer;                         \
375 376 377
            strm->avail_in--;                            \
            strm->total_in++;                            \
            state->acc <<= 8;                            \
378
            state->acc |= *strm->next_in++;              \
379 380
            state->bitp += 8;                            \
        }                                                \
381
    } while (0)
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
382

383 384 385 386 387
#define GET(n)                                                  \
    ((state->acc >> (state->bitp - (n))) & ((1ULL << (n)) - 1))

#define DROP(n) state->bitp -= (unsigned)(n)

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
#define ASKFS()                                                     \
    do {                                                            \
        ASK(1);                                                     \
        while ((state->acc & (1ULL << (state->bitp - 1))) == 0) {   \
            if (state->bitp == 1) {                                 \
                if (strm->avail_in == 0)                            \
                    goto req_buffer;                                \
                strm->avail_in--;                                   \
                strm->total_in++;                                   \
                state->acc <<= 8;                                   \
                state->acc |= *strm->next_in++;                     \
                state->bitp += 8;                                   \
            }                                                       \
            state->fs++;                                            \
            state->bitp--;                                          \
        }                                                           \
404
    } while (0)
405 406 407

#define GETFS() state->fs

408 409 410 411 412 413 414
#define DROPFS()                                \
    do {                                        \
        state->fs = 0;                          \
        /* Needs to be here for                 \
           ASK/GET/PUT/DROP interleaving. */    \
        state->bitp--;                          \
    } while (0)
415 416 417

#define PUT(sample)                                \
    do {                                           \
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
418 419
        if (strm->avail_out == 0)                  \
            goto req_buffer;                       \
420 421 422 423 424 425 426 427 428 429 430
        u_put(strm, (sample));                     \
    } while (0)

#define COPYSAMPLE()                    \
    do {                                \
        ASK(strm->bit_per_sample);      \
        PUT(GET(strm->bit_per_sample)); \
        DROP(strm->bit_per_sample);     \
    } while (0)


Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
431
int aec_decode(struct aec_stream *strm, int flush)
432
{
433 434 435 436 437 438 439 440 441
    /**
       Finite-state machine implementation of the adaptive entropy
       decoder.

       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.
    */

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
442
    int zero_blocks;
443
    int64_t gamma, beta, ms, delta1;
444 445 446 447 448
    int k;
    decode_state *state;

    state = strm->state;

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
449 450
    for (;;) {
        switch(state->mode) {
451
        case M_ID:
452
            if (state->pp
453
                && (state->samples_out / strm->block_size) % strm->rsi == 0)
454 455 456 457 458 459 460
                state->ref = 1;
            else
                state->ref = 0;

            ASK(state->id_len);
            state->id = GET(state->id_len);
            DROP(state->id_len);
461 462 463 464
            state->mode = state->id_table[state->id];
            break;

        case M_SPLIT:
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
465
            if (SAFE) {
466 467 468 469 470
                fast_split(strm);
                state->mode = M_ID;
                break;
            }

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
471
            if (state->ref) {
472 473
                COPYSAMPLE();
                state->n = strm->block_size - 1;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
474
            } else {
475 476 477
                state->n = strm->block_size;
            }

478
            state->i = state->n - 1;
479 480 481
            state->mode = M_SPLIT_FS;

        case M_SPLIT_FS:
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
482
            do {
483
                ASKFS();
484
                state->block[state->i] = GETFS();
485
                DROPFS();
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
486
            } while(state->i--);
487

488
            state->i = state->n - 1;
489
            state->mode = M_SPLIT_OUTPUT;
490

491
        case M_SPLIT_OUTPUT:
492
            k = state->id - 1;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
493
            do {
494
                ASK(k);
495
                PUT((state->block[state->i] << k) + GET(k));
496
                DROP(k);
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
497
            } while(state->i--);
498 499 500 501 502 503 504 505 506 507 508

            state->mode = M_ID;
            break;

        case M_LOW_ENTROPY:
            ASK(1);
            state->id = GET(1);
            DROP(1);
            state->mode = M_LOW_ENTROPY_REF;

        case M_LOW_ENTROPY_REF:
509
            if (state->ref)
510 511
                COPYSAMPLE();

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
512
            if(state->id == 1) {
513 514 515 516 517 518 519 520 521 522 523
                state->mode = M_SE;
                break;
            }

            state->mode = M_ZERO_BLOCK;

        case M_ZERO_BLOCK:
            ASKFS();
            zero_blocks = GETFS() + 1;
            DROPFS();

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
524
            if (zero_blocks == ROS) {
525
                zero_blocks =  64 - (
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
526
                    (state->samples_out / strm->block_size)
527
                    % strm->rsi % 64);
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
528
            } else if (zero_blocks > ROS) {
529 530
                zero_blocks--;
            }
531

532
            if (state->ref)
533 534 535 536
                state->i = zero_blocks * strm->block_size - 1;
            else
                state->i = zero_blocks * strm->block_size;

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
537
            if (strm->avail_out >= state->i * state->byte_per_sample) {
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
                fast_zero(strm);
                state->mode = M_ID;
                break;
            }

            state->mode = M_ZERO_OUTPUT;

        case M_ZERO_OUTPUT:
            do
                PUT(0);
            while(--state->i);

            state->mode = M_ID;
            break;

        case M_SE:
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
554
            if (SAFE) {
555 556 557 558 559 560
                fast_se(strm);
                state->mode = M_ID;
                break;
            }

            state->mode = M_SE_DECODE;
561
            state->i = state->ref;
562 563

        case M_SE_DECODE:
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
564
            while(state->i < strm->block_size) {
565
                ASKFS();
566 567 568 569 570
                gamma = GETFS();
                beta = second_extension[gamma][0];
                ms = second_extension[gamma][1];
                delta1 = gamma - ms;

Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
571
                if ((state->i & 1) == 0) {
572 573 574 575 576
                    PUT(beta - delta1);
                    state->i++;
                }

                PUT(delta1);
577
                state->i++;
578
                DROPFS();
579 580
            }

581
            state->mode = M_ID;
582
            break;
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
583

584
        case M_UNCOMP:
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
585
            if (SAFE) {
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
                fast_uncomp(strm);
                state->mode = M_ID;
                break;
            }

            state->i = strm->block_size;
            state->mode = M_UNCOMP_COPY;

        case M_UNCOMP_COPY:
            do
                COPYSAMPLE();
            while(--state->i);

            state->mode = M_ID;
            break;

        default:
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
603
            return AEC_STREAM_ERROR;
604 605
        }
    }
606 607

req_buffer:
Mathis Rosenhauer's avatar
Mathis Rosenhauer committed
608
    return AEC_OK;
609
}