On Fri, Mar 07, 2014 at 03:31:13PM +0100, Diego Biurrun wrote:
> From: Maxim Poliakovski <[email protected]>
> 
> JPEG part decoding and minor improvements for ePIC decoder by Kostya Shishkov.
> 
> Signed-off-by: Diego Biurrun <[email protected]>
> ---
>  Changelog            |    1 +
>  doc/general.texi     |    2 +
>  libavcodec/Makefile  |    2 +-
>  libavcodec/elsdec.c  |  414 +++++++++++++++++++++++++++++
>  libavcodec/elsdec.h  |   65 +++++
>  libavcodec/g2meet.c  |  705 
> +++++++++++++++++++++++++++++++++++++++++++++++++-
>  libavcodec/version.h |    4 +-
>  7 files changed, 1177 insertions(+), 16 deletions(-)
>  create mode 100644 libavcodec/elsdec.c
>  create mode 100644 libavcodec/elsdec.h
> 
> diff --git a/libavcodec/elsdec.c b/libavcodec/elsdec.c
> new file mode 100644
> index 0000000..a2da0db
> --- /dev/null
> +++ b/libavcodec/elsdec.c
> @@ -0,0 +1,414 @@
> +/*
> + * ELS (Entropy Logarithmic-Scale) decoder
> + *
> + * Copyright (c) 2013 Maxim Poliakovski
> + *
> + * This file is part of Libav.
> + *
> + * Libav 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.
> + *
> + * Libav 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 Libav; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +/**
> + * @file
> + * Entropy Logarithmic-Scale binary arithmetic coder
> + */
> +
> +#include <math.h>
> +
> +#include "libavutil/common.h"
> +#include "libavutil/intreadwrite.h"
> +
> +#include "avcodec.h"
> +#include "elsdec.h"
> +
> +/* ELS coder constants and structures. */
> +#define ELS_JOTS_PER_BYTE 36
> +#define ELS_MAX           (1 << 24)
> +
> +/* ELS coder tables. */
> +static const struct Ladder {
> +    short AMps;
> +    short ALps;
> +    unsigned char next0;
> +    unsigned char next1;

maybe int16_t+uint8_t ?

> +} Ladder[174] = {
[...]
> +
> +static int els_exp_tab[145];
> +static const int *pAllowable = &els_exp_tab[108];

You can replace that with ELS_JOTS_PER_PYTE*x (+1) if you don't like magic
constants, the logic can be seen in the function right below.

> +
> +av_cold void ff_els_generate_exp_table(void)
> +{
> +    int i;
> +    float jot_size;
> +
> +    jot_size = 8.0f / ELS_JOTS_PER_BYTE;
> +
> +    for (i = 0; i < ELS_JOTS_PER_BYTE; i++) {
> +        els_exp_tab[i]       = 0;
> +        els_exp_tab[i +  72] = floor(pow(2.0f, (i + 36) * jot_size));
> +        els_exp_tab[i +  36] = els_exp_tab[i + 72] >> 8;
> +        els_exp_tab[i + 108] = els_exp_tab[i + 72] << 8;
> +    }
> +
> +    els_exp_tab[144] = ELS_MAX;
> +}
> +
[...]
> +unsigned int ff_els_decode_unsigned(ElsDecCtx *ctx, ElsUnsignedRung *ur)
> +{
> +    int i, n, r, bit, pos;
> +    ElsRungNode *rung_node;
> +
> +    if (ctx->err != ELS_NOERR)
> +        return 0;
> +
> +    /* decode unary prefix */
> +    for (n = 0; n < ELS_EXPGOLOMB_LEN + 1 && !ff_els_decode_bit(ctx, 
> &ur->prefix_rung[n]); n++)
> +        ;

function call can be moved into loop body to shorten the line

> +
> +    /* handle the error/overflow case */
> +    if (ctx->err || n >= ELS_EXPGOLOMB_LEN) {
> +        ctx->err = ELS_OVERFLOW;
> +        return 0;
> +    }
> +
> +    /* handle the zero case */
> +    if (!n)
> +        return 0;
> +
> +    /* initialize probability tree */
> +    if (!ur->rem_rung_list) {
> +        ur->rem_rung_list = av_mallocz(64 * sizeof(ElsRungNode));
> +        if (!ur->rem_rung_list) {
> +            ctx->err = ELS_NOMEM; // Probability tree initialization failed
> +            return 0;
> +        }
> +        ur->rung_list_size = 64 * sizeof(ElsRungNode);
> +        ur->avail_index    = ELS_EXPGOLOMB_LEN;
> +    }
> +
> +    /* decode the remainder */
> +    for (i = 0, r = 0, bit = 0; i < n; i++) {
> +        if (!i) {
> +            rung_node = &ur->rem_rung_list[n];
> +        } else {
> +            if (!rung_node->next_index) {
> +                if (ur->rung_list_size <= (ur->avail_index + 2) * 
> sizeof(ElsRungNode)) {
> +                    // remember rung_node position
> +                    pos               = rung_node - ur->rem_rung_list;
> +                    ur->rem_rung_list = av_realloc(ur->rem_rung_list,
> +                                                   ur->rung_list_size +
> +                                                   64 * sizeof(ElsRungNode));

reallocp?

> +                    if (!ur->rem_rung_list) {
> +                        ctx->err = ELS_NOMEM; // Probability tree resize 
> failed
> +                        return 0;
> +                    }
> +                    memset(((char *) ur->rem_rung_list) + ur->rung_list_size,
> +                           0, 64 * sizeof(ElsRungNode));
> +                    ur->rung_list_size += 64 * sizeof(ElsRungNode);
> +                    // restore rung_node position in the new list
> +                    rung_node           = &ur->rem_rung_list[pos];
> +                }
> +                rung_node->next_index = ur->avail_index;
> +                ur->avail_index      += 2;
> +            }
> +            rung_node = &ur->rem_rung_list[rung_node->next_index + bit];
> +        }
> +
> +        bit = ff_els_decode_bit(ctx, &rung_node->rung);
> +        if (ctx->err != ELS_NOERR)
> +            return -1;
> +
> +        r = (r << 1) + bit;
> +    }
> +
> +    return (1 << n) - 1 + r; /* make value from exp golomb code */
> +}
[...]
> diff --git a/libavcodec/g2meet.c b/libavcodec/g2meet.c
> index 28bed42..c11db66 100644
> --- a/libavcodec/g2meet.c
> +++ b/libavcodec/g2meet.c
[...]
> +static int epic_decode_run_length(ePICContext *dc, int x, int y,
> +                                  int tile_width, uint32_t *curr_row,
> +                                  uint32_t *above_row, uint32_t *above2_row,
> +                                  uint32_t *pPix, int *pRun)
> +{
> +    int idx, run, rle, got_pixel, WWneW, old_WWneW, NWneW;
> +    int start_pos, pos, flag;
> +    uint32_t pix, W, WW, N, NN, NW, NE, NWW, NNW, NNE;
> +
> +    *pRun     = 0;
> +    old_WWneW = 0;
> +    got_pixel = 0;
> +
> +    LOAD_NEIGHBOURS(x);
> +
> +    if (dc->next_run_pos == x) {
> +        /* can't reuse W for the new pixel in this case */
> +        WWneW = 1;
> +    } else {
> +        idx = (WW  != W)  << 7 |
> +              (NW  != W)  << 6 |
> +              (N   != NE) << 5 |
> +              (NW  != N)  << 4 |
> +              (NWW != NW) << 3 |
> +              (NNE != NE) << 2 |
> +              (NN  != N)  << 1 |
> +              (NNW != NW);
> +        WWneW = ff_els_decode_bit(&dc->els_ctx, &dc->W_ctx_rung[idx]);
> +    }
> +
> +    if (WWneW)
> +        dc->stack[dc->stack_pos++] = W;
> +    else {
> +        *pPix     = W;
> +        got_pixel = 1;
> +    }
> +
> +    do {
> +        if (got_pixel) // pixel value already known (derived from either W 
> or N)
> +            NWneW = *pPix != N;
> +        else { // pixel value is unknown and will be decoded later
> +            NWneW = *pRun ? NWneW : NW != W;
> +
> +            /* TODO: RFC this mess! */
> +            switch (((NW != N) << 2) | (NWneW << 1) | WWneW) {
> +            case 0:
> +                av_log(NULL, AV_LOG_ERROR, "Haltepunkt 301, x_pos=%d, 
> y_pos=%d\n", x, y);

maybe drop this message (and similar one below)?

> +                break;
> +            case 3:
> +            case 5:
> +            case 6:
> +            case 7:
> +                if (!is_pixel_on_stack(dc, N)) {
> +                    idx = WWneW << 8 |
> +                          (*pRun ? old_WWneW : WW != W) << 7 |
> +                          NWneW << 6 |
> +                          (N != NE) << 5 |
> +                          (NW != N) << 4 |
> +                          (NWW != NW) << 3 |
> +                          (NNE != NE) << 2 |
> +                          (NN != N) << 1 |
> +                          (NNW != NW);

this should be valigned a bit like below

> +                    if (!ff_els_decode_bit(&dc->els_ctx, 
> &dc->N_ctx_rung[idx])) {
> +                        NWneW     = 0;
> +                        *pPix     = N;
> +                        got_pixel = 1;
> +                        break;
> +                    }
> +                }
> +            /* FALLTHROUGH */
> +            default:
> +                NWneW     = 1;
> +                old_WWneW = WWneW;
> +                if (!is_pixel_on_stack(dc, N))
> +                    dc->stack[dc->stack_pos++] = N;
> +            }
> +        }
> +
> +        (*pRun)++;
> +        if (x + *pRun >= tile_width - 1)
> +            break;
> +
> +        UPDATE_NEIGHBOURS(x + *pRun);
> +
> +        if (!NWneW && NW == N && N == NE) {
> +            start_pos = x + *pRun;
> +
> +            /* scan for a run of pix in the line above */
> +            pix = above_row[start_pos + 1];
> +            for (pos = start_pos + 2;
> +                 pos < tile_width && above_row[pos] == pix; pos++) ;
> +            run = pos - start_pos - 1;
> +            idx = log2_ceil(run);
> +            if (ff_els_decode_bit(&dc->els_ctx, &dc->prev_row_rung[idx]))
> +                *pRun += run;
> +            else {
> +                /* run-length is coded as plain binary number of idx-1 bits 
> */
> +                for (pos = idx - 1, rle = 0, flag = 0; pos >= 0; pos--) {
> +                    if ((1 << pos) + rle < run &&
> +                        ff_els_decode_bit(&dc->els_ctx,
> +                                          flag ? &dc->runlen_one :
> +                                          &dc->runlen_zeroes[pos])) {
> +                        flag = 1;
> +                        rle |= 1 << pos;
> +                    }
> +                }
> +                *pRun += rle;
> +                break; // return immediately
> +            }
> +            if (x + *pRun >= tile_width - 1)
> +                break;
> +
> +            LOAD_NEIGHBOURS(x + *pRun);
> +            WWneW = 0;
> +            NWneW = 0;
> +        }
> +
> +        idx = WWneW       << 7 |
> +              NWneW       << 6 |
> +              (N   != NE) << 5 |
> +              (NW  != N)  << 4 |
> +              (NWW != NW) << 3 |
> +              (NNE != NE) << 2 |
> +              (NN  != N)  << 1 |
> +              (NNW != NW);
> +        WWneW = ff_els_decode_bit(&dc->els_ctx, &dc->W_ctx_rung[idx]);
> +    } while (!WWneW);
> +
> +    dc->next_run_pos = x + *pRun;
> +    return got_pixel;
> +}
> +
[...]
> +static int epic_jb_decode_tile(G2MContext *c, int tile_x, int tile_y,
> +                               const uint8_t *src, int src_size,
> +                               AVCodecContext *avctx)
> +{
> +    uint8_t prefix, mask, tr_r, tr_g, tr_b, tr;
> +    int extrabytes, ret, tile_width, tile_height, i, j, k;
> +    unsigned int els_dsize;
> +    uint8_t *buf, *dst, *out, *jpg;
> +    uint32_t *in;
> +
> +    if (!src_size)
> +        return 0;
> +
> +    /* get data size of the ELS partition as unsigned variable-length 
> integer */
> +    prefix = *src++;
> +    for (extrabytes = 0, mask = 0x80; (prefix & mask) && (extrabytes < 7);
> +         mask >>= 1, extrabytes++) ;
> +    if (extrabytes > 3 || --src_size < extrabytes) {
> +        av_log(avctx, AV_LOG_ERROR, "ePIC: invalid data size VLI\n");

VLC would be more conventional name than VLI (especially if you consider
function name ;)

[...]

the rest should be more or less OK
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to