static int shorten_decode_frame(AVCodecContext *avctx,

        void *data, int *data_size,

        uint8_t *buf, int buf_size)

{

    ShortenContext *s = avctx->priv_data;

    int i, input_buf_size = 0;

    int16_t *samples = data;

    if(s->max_framesize == 0){

        s->max_framesize= 1024; // should hopefully be enough for the first header

        s->bitstream= av_fast_realloc(s->bitstream, &s->allocated_bitstream_size, s->max_framesize);

    }



    if(1 && s->max_framesize){//FIXME truncated

        buf_size= FFMIN(buf_size, s->max_framesize - s->bitstream_size);

        input_buf_size= buf_size;



        if(s->bitstream_index + s->bitstream_size + buf_size > s->allocated_bitstream_size){

            //                printf("memmove\n");

            memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size);

            s->bitstream_index=0;

        }

        memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, buf_size);

        buf= &s->bitstream[s->bitstream_index];

        buf_size += s->bitstream_size;

        s->bitstream_size= buf_size;



        if(buf_size < s->max_framesize){

            //dprintf("wanna more data ... %d\n", buf_size);

            return input_buf_size;

        }

    }

    init_get_bits(&s->gb, buf, buf_size*8);

    get_bits(&s->gb, s->bitindex);

    if (!s->blocksize)

    {

        int maxnlpc = 0;

        /* shorten signature */

        if (get_bits_long(&s->gb, 32) != bswap_32(ff_get_fourcc("ajkg"))) {

            av_log(s->avctx, AV_LOG_ERROR, "missing shorten magic 'ajkg'\n");

            return -1;

        }



        s->lpcqoffset = 0;

        s->blocksize = DEFAULT_BLOCK_SIZE;

        s->channels = 1;

        s->nmean = -1;

        s->version = get_bits(&s->gb, 8);

        s->internal_ftype = get_uint(s, TYPESIZE);



        s->channels = get_uint(s, CHANSIZE);

        if (s->channels > MAX_CHANNELS) {

            av_log(s->avctx, AV_LOG_ERROR, "too many channels: %d\n", s->channels);

            return -1;

        }



        /* get blocksize if version > 0 */

        if (s->version > 0) {

            int skip_bytes;

            s->blocksize = get_uint(s, av_log2(DEFAULT_BLOCK_SIZE));

            maxnlpc = get_uint(s, LPCQSIZE);

            s->nmean = get_uint(s, 0);



            skip_bytes = get_uint(s, NSKIPSIZE);

            for (i=0; i<skip_bytes; i++) {

                skip_bits(&s->gb, 8);

            }

        }

        s->nwrap = FFMAX(NWRAP, maxnlpc);



        allocate_buffers(s);



        init_offset(s);



        if (s->version > 1)

            s->lpcqoffset = V2LPCQOFFSET;



        if (get_ur_golomb_shorten(&s->gb, FNSIZE) != FN_VERBATIM) {

            av_log(s->avctx, AV_LOG_ERROR, "missing verbatim section at begining of stream\n");

            return -1;

        }



        s->header_size = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE);

        if (s->header_size >= OUT_BUFFER_SIZE || s->header_size < CANONICAL_HEADER_SIZE) {

            av_log(s->avctx, AV_LOG_ERROR, "header is wrong size: %d\n", s->header_size);

            return -1;

        }



        for (i=0; i<s->header_size; i++)

            s->header[i] = (char)get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE);



        if (decode_wave_header(avctx, s->header, s->header_size) < 0)

            return -1;



        s->cur_chan = 0;

        s->bitshift = 0;

    }

    else

    {

        int cmd;

        int len;

        cmd = get_ur_golomb_shorten(&s->gb, FNSIZE);

        switch (cmd) {

            case FN_ZERO:

            case FN_DIFF0:

            case FN_DIFF1:

            case FN_DIFF2:

            case FN_DIFF3:

            case FN_QLPC:

                {

                    int residual_size = 0;

                    int channel = s->cur_chan;

                    int32_t coffset;

                    if (cmd != FN_ZERO) {

                        residual_size = get_ur_golomb_shorten(&s->gb, ENERGYSIZE);

                        /* this is a hack as version 0 differed in defintion of get_sr_golomb_shorten */

                        if (s->version == 0)

                            residual_size--;

                    }



                    if (s->nmean == 0)

                        coffset = s->offset[channel][0];

                    else {

                        int32_t sum = (s->version < 2) ? 0 : s->nmean / 2;

                        for (i=0; i<s->nmean; i++)

                            sum += s->offset[channel][i];

                        coffset = sum / s->nmean;

                        if (s->version >= 2)

                            coffset >>= FFMIN(1, s->bitshift);

                    }

                    switch (cmd) {

                        case FN_ZERO:

                            for (i=0; i<s->blocksize; i++)

                                s->decoded[channel][i] = 0;

                            break;

                        case FN_DIFF0:

                            for (i=0; i<s->blocksize; i++)

                                s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + coffset;

                            break;

                        case FN_DIFF1:

                            for (i=0; i<s->blocksize; i++)

                                s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + s->decoded[channel][i - 1];

                            break;

                        case FN_DIFF2:

                            for (i=0; i<s->blocksize; i++)

                                s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + 2*s->decoded[channel][i-1]

                                                                                                      -   s->decoded[channel][i-2];

                            break;

                        case FN_DIFF3:

                            for (i=0; i<s->blocksize; i++)

                                s->decoded[channel][i] = get_sr_golomb_shorten(&s->gb, residual_size) + 3*s->decoded[channel][i-1]

                                                                                                      - 3*s->decoded[channel][i-2]

                                                                                                      +   s->decoded[channel][i-3];

                            break;

                        case FN_QLPC:

                            {

                                int pred_order = get_ur_golomb_shorten(&s->gb, LPCQSIZE);

                                for (i=0; i<pred_order; i++)

                                    s->decoded[channel][i - pred_order] -= coffset;

                                decode_subframe_lpc(s, channel, residual_size, pred_order);

                                if (coffset != 0)

                                    for (i=0; i < s->blocksize; i++)

                                        s->decoded[channel][i] += coffset;

                            }

                    }

                    if (s->nmean > 0) {

                        int32_t sum = (s->version < 2) ? 0 : s->blocksize / 2;

                        for (i=0; i<s->blocksize; i++)

                            sum += s->decoded[channel][i];



                        for (i=1; i<s->nmean; i++)

                            s->offset[channel][i-1] = s->offset[channel][i];



                        if (s->version < 2)

                            s->offset[channel][s->nmean - 1] = sum / s->blocksize;

                        else

                            s->offset[channel][s->nmean - 1] = (sum / s->blocksize) << s->bitshift;

                    }

                    for (i=-s->nwrap; i<0; i++)

                        s->decoded[channel][i] = s->decoded[channel][i + s->blocksize];



                    fix_bitshift(s, s->decoded[channel]);



                    s->cur_chan++;

                    if (s->cur_chan == s->channels) {

                        samples = interleave_buffer(samples, s->channels, s->blocksize, s->decoded);

                        s->cur_chan = 0;

                        goto frame_done;

                    }

                    break;

                }

                break;

            case FN_VERBATIM:

                len = get_ur_golomb_shorten(&s->gb, VERBATIM_CKSIZE_SIZE);

                while (len--) {

                    get_ur_golomb_shorten(&s->gb, VERBATIM_BYTE_SIZE);

                }

                break;

            case FN_BITSHIFT:

                s->bitshift = get_ur_golomb_shorten(&s->gb, BITSHIFTSIZE);

                break;

            case FN_BLOCKSIZE:

                s->blocksize = get_uint(s, av_log2(s->blocksize));

                break;

            case FN_QUIT:

                return buf_size;

                break;

            default:

                av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd);

                return -1;

                break;

        }

    }

frame_done:

    *data_size = (int8_t *)samples - (int8_t *)data;



    //    s->last_blocksize = s->blocksize;

    s->bitindex = get_bits_count(&s->gb) - 8*((get_bits_count(&s->gb))/8);

    i= (get_bits_count(&s->gb))/8;

    if (i > buf_size) {

        av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", i - buf_size);

        s->bitstream_size=0;

        s->bitstream_index=0;

        return -1;

    }

    if (s->bitstream_size) {

        s->bitstream_index += i;

        s->bitstream_size  -= i;

        return input_buf_size;

    } else

        return i;

}
