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