/*
 * Copyright (C) 2016 Open Broadcast Systems Ltd.
 * Author        2016 Rostislav Pehlivanov <rpehlivanov@obe.tv>
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include "dirac_vlc.h"

#define LUT_SIZE   (1 << LUT_BITS)
#define RSIZE_BITS (CHAR_BIT*sizeof(residual))

#define CONVERT_TO_RESIDUE(a, b)                                               \
    (((residual)(a)) << (RSIZE_BITS - (b)))

#define INIT_RESIDUE(N)                                                        \
    residual N = 0;                                                            \
    av_unused int32_t N ## _bits  = 0

#define SET_RESIDUE(N, I, B)                                                   \
    N          = CONVERT_TO_RESIDUE(I, B);                                     \
    N ## _bits = B

#define APPEND_RESIDUE(N, M)                                                   \
    N          |= M >> (N ## _bits);                                           \
    N ## _bits  = (N ## _bits + (M ## _bits)) & 0x3F

int ff_dirac_golomb_read_32bit(DiracGolombLUT *lut_ctx, const uint8_t *buf,
                               int bytes, uint8_t *_dst, int coeffs)
{
    int i, b, c_idx = 0;
    int32_t *dst = (int32_t *)_dst;
    DiracGolombLUT *future[4], *l = &lut_ctx[2*LUT_SIZE + buf[0]];
    INIT_RESIDUE(res);

    for (b = 1; b <= bytes; b++) {
        future[0] = &lut_ctx[buf[b]];
        future[1] = future[0] + 1*LUT_SIZE;
        future[2] = future[0] + 2*LUT_SIZE;
        future[3] = future[0] + 3*LUT_SIZE;

        if ((c_idx + 1) > coeffs)
            return c_idx;

        /* res_bits is a hint for better branch prediction */
        if (res_bits && l->sign) {
            int32_t coeff = 1;
            APPEND_RESIDUE(res, l->preamble);
            for (i = 0; i < (res_bits >> 1) - 1; i++) {
                coeff <<= 1;
                coeff |= (res >> (RSIZE_BITS - 2*i - 2)) & 1;
            }
            dst[c_idx++] = l->sign * (coeff - 1);
            res_bits = res = 0;
        }

        memcpy(&dst[c_idx], l->ready, LUT_BITS*sizeof(int32_t));
        c_idx += l->ready_num;

        APPEND_RESIDUE(res, l->leftover);

        l = future[l->need_s ? 3 : !res_bits ? 2 : res_bits & 1];
    }

    return c_idx;
}

int ff_dirac_golomb_read_16bit(DiracGolombLUT *lut_ctx, const uint8_t *buf,
                               int bytes, uint8_t *_dst, int coeffs)
{
    int i, b, c_idx = 0;
    int16_t *dst = (int16_t *)_dst;
    DiracGolombLUT *future[4], *l = &lut_ctx[2*LUT_SIZE + buf[0]];
    INIT_RESIDUE(res);

    for (b = 1; b <= bytes; b++) {
        future[0] = &lut_ctx[buf[b]];
        future[1] = future[0] + 1*LUT_SIZE;
        future[2] = future[0] + 2*LUT_SIZE;
        future[3] = future[0] + 3*LUT_SIZE;

        if ((c_idx + 1) > coeffs)
            return c_idx;

        if (res_bits && l->sign) {
            int32_t coeff = 1;
            APPEND_RESIDUE(res, l->preamble);
            for (i = 0; i < (res_bits >> 1) - 1; i++) {
                coeff <<= 1;
                coeff |= (res >> (RSIZE_BITS - 2*i - 2)) & 1;
            }
            dst[c_idx++] = l->sign * (coeff - 1);
            res_bits = res = 0;
        }

        for (i = 0; i < LUT_BITS; i++)
            dst[c_idx + i] = l->ready[i];
        c_idx += l->ready_num;

        APPEND_RESIDUE(res, l->leftover);

        l = future[l->need_s ? 3 : !res_bits ? 2 : res_bits & 1];
    }

    return c_idx;
}

/* Searches for golomb codes in a residue */
static inline void search_for_golomb(DiracGolombLUT *l, residual r, int bits)
{
    int r_count = RSIZE_BITS - 1;
    int bits_start, bits_tot = bits, need_sign = 0;

#define READ_BIT(N) (((N) >> (N ## _count--)) & 1)

    while (1) {
        int32_t coef = 1;
        bits_start = (RSIZE_BITS - 1) - r_count;

        while (1) {
            if (!bits--)
                goto leftover;
            if (READ_BIT(r))
                break;

            coef <<= 1;

            if (!bits--)
                goto leftover;
            coef |= READ_BIT(r);
        }

        l->ready[l->ready_num] = coef - 1;
        if (l->ready[l->ready_num]) {
            if (!bits--) {
                need_sign = 1;
                goto leftover;
            }
            l->ready[l->ready_num] *= READ_BIT(r) ? -1 : +1;
        }
        l->ready_num++;

        if (!bits)
            return;
    }

    leftover:
        l->leftover      = r << bits_start;
        l->leftover_bits = bits_tot - bits_start;
        l->need_s        = need_sign;
}

/* Parity LUTs - even and odd bit end positions */
static void generate_parity_lut(DiracGolombLUT *lut, int even)
{
    int idx;
    for (idx = 0; idx < LUT_SIZE; idx++) {
        DiracGolombLUT *l = &lut[idx];
        int symbol_end_loc = -1;
        uint32_t code;
        int i;

        INIT_RESIDUE(res);
        SET_RESIDUE(res, idx, LUT_BITS);

        for (i = 0; i < LUT_BITS; i++) {
            const int cond = even ? (i & 1) : !(i & 1);
            if (((res >> (RSIZE_BITS - i - 1)) & 1) && cond) {
                symbol_end_loc = i + 2;
                break;
            }
        }

        if (symbol_end_loc < 0 || symbol_end_loc > LUT_BITS) {
            l->preamble      = 0;
            l->preamble_bits = 0;
            l->leftover_bits = LUT_BITS;
            l->leftover      = CONVERT_TO_RESIDUE(idx, l->leftover_bits);
            if (even)
                l->need_s    = idx & 1;
            continue;
        }

        /* Gets bits 0 through to (symbol_end_loc - 1) inclusive */
        code  = idx >> ((LUT_BITS - 1) - (symbol_end_loc - 1));
        code &= ((1 << LUT_BITS) - 1) >> (LUT_BITS - symbol_end_loc);
        l->preamble_bits = symbol_end_loc;
        l->preamble      = CONVERT_TO_RESIDUE(code, l->preamble_bits);
        l->sign = ((l->preamble >> (RSIZE_BITS - l->preamble_bits)) & 1) ? -1 : +1;

        search_for_golomb(l, res << symbol_end_loc, LUT_BITS - symbol_end_loc);
    }
}

/* Reset (off == 0) and needs-one-more-bit (off == 1) LUTs */
static void generate_offset_lut(DiracGolombLUT *lut, int off)
{
    int idx;
    for (idx = 0; idx < LUT_SIZE; idx++) {
        DiracGolombLUT *l = &lut[idx];

        INIT_RESIDUE(res);
        SET_RESIDUE(res, idx, LUT_BITS);

        l->preamble_bits = off;
        if (off) {
            l->preamble  = CONVERT_TO_RESIDUE(res >> (RSIZE_BITS - off), off);
            l->sign      = ((l->preamble >> (RSIZE_BITS - l->preamble_bits)) & 1) ? -1 : +1;
        } else {
            l->preamble  = 0;
            l->sign = 1;
        }

        search_for_golomb(l, res << off, LUT_BITS - off);
    }
}

av_cold int ff_dirac_golomb_reader_init(DiracGolombLUT **lut_ctx)
{
    DiracGolombLUT *lut;

    if (!(lut = av_calloc(4*LUT_SIZE, sizeof(DiracGolombLUT))))
        return AVERROR(ENOMEM);

    generate_parity_lut(&lut[0*LUT_SIZE], 0);
    generate_parity_lut(&lut[1*LUT_SIZE], 1);
    generate_offset_lut(&lut[2*LUT_SIZE], 0);
    generate_offset_lut(&lut[3*LUT_SIZE], 1);

    *lut_ctx = lut;

    return 0;
}

av_cold void ff_dirac_golomb_reader_end(DiracGolombLUT **lut_ctx)
{
    av_freep(lut_ctx);
}
