Merge commit '08c2d8f0aa679c2f060721d1d0d4f33d2ae32368'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 1 Jul 2015 01:18:30 +0000 (03:18 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 1 Jul 2015 01:18:30 +0000 (03:18 +0200)
* commit '08c2d8f0aa679c2f060721d1d0d4f33d2ae32368':
  Go2Meeting decoder

Conflicts:
Changelog
libavcodec/g2meet.c
libavcodec/version.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
Changelog
doc/general.texi
libavcodec/Makefile
libavcodec/elsdec.c
libavcodec/elsdec.h
libavcodec/g2meet.c
libavcodec/version.h

diff --cc Changelog
+++ b/Changelog
@@@ -2,70 -2,17 +2,71 @@@ Entries are sorted chronologically fro
  releases are sorted from youngest to oldest.
  
  version <next>:
 -- aliases and defaults for Ogg subtypes (opus, spx)
 -- HEVC/H.265 RTP payload format (draft v6) packetizer and depacketizer
 -- avplay now exits by default at the end of playback
 -- XCB-based screen-grabber
 -- creating DASH compatible fragmented MP4, MPEG-DASH segmenting muxer
 -- H.261 RTP payload format (RFC 4587) depacketizer and experimental packetizer
 +- colorkey video filter
 +- BFSTM/BCSTM demuxer
 +- little-endian ADPCM_THP decoder
 +- Hap decoder and encoder
 +- DirectDraw Surface image/texture decoder
 +- ssim filter
 +- rewritten ASF demuxer
 +- showvolume filter
 +- Many improvements to the JPEG 2000 decoder
++- Go2Meeting decoding support
 +
 +
 +version 2.7:
 +- FFT video filter
 +- TDSC decoder
 +- DTS lossless extension (XLL) decoding (not lossless, disabled by default)
 +- showwavespic filter
 +- DTS decoding through libdcadec
 +- Drop support for nvenc API before 5.0
 +- nvenc HEVC encoder
 +- Detelecine filter
 +- Intel QSV-accelerated H.264 encoding
 +- MMAL-accelerated H.264 decoding
 +- basic APNG encoder and muxer with default extension "apng"
 +- unpack DivX-style packed B-frames in MPEG-4 bitstream filter
 +- WebM Live Chunk Muxer
 +- nvenc level and tier options
 +- chorus filter
 +- Canopus HQ/HQA decoder
 +- Automatically rotate videos based on metadata in ffmpeg
 +- improved Quickdraw compatibility
 +- VP9 high bit-depth and extended colorspaces decoding support
 +- WebPAnimEncoder API when available for encoding and muxing WebP
 +- Direct3D11-accelerated decoding
 +- Support Secure Transport
 +- Multipart JPEG demuxer
 +
 +
 +version 2.6:
 +- nvenc encoder
 +- 10bit spp filter
 +- colorlevels filter
 +- RIFX format for *.wav files
  - RTP/mpegts muxer
 -- VP8 in Ogg demuxing
 +- non continuous cache protocol support
 +- tblend filter
 +- cropdetect support for non 8bpp, absolute (if limit >= 1) and relative (if limit < 1.0) threshold
 +- Camellia symmetric block cipher
  - OpenH264 encoder wrapper
 +- VOC seeking support
 +- Closed caption Decoder
 +- fspp, uspp, pp7 MPlayer postprocessing filters ported to native filters
 +- showpalette filter
 +- Twofish symmetric block cipher
  - Support DNx100 (960x720@8)
 -- Direct3D11-accelerated decoding
 +- eq2 filter ported from libmpcodecs as eq filter
 +- removed libmpcodecs
 +- Changed default DNxHD colour range in QuickTime .mov derivatives to mpeg range
 +- ported softpulldown filter from libmpcodecs as repeatfields filter
 +- dcshift filter
 +- RTP depacketizer for loss tolerant payload format for MP3 audio (RFC 5219)
 +- RTP depacketizer for AC3 payload format (RFC 4184)
 +- palettegen and paletteuse filters
 +- VP9 RTP payload format (draft 0) experimental depacketizer
 +- RTP depacketizer for DV (RFC 6469)
  - DXVA2-accelerated HEVC decoding
  - AAC ELD 480 decoding
  - Intel QSV-accelerated H.264 decoding
Simple merge
@@@ -257,11 -214,9 +257,11 @@@ OBJS-$(CONFIG_FLIC_DECODER)            
  OBJS-$(CONFIG_FOURXM_DECODER)          += 4xm.o
  OBJS-$(CONFIG_FRAPS_DECODER)           += fraps.o
  OBJS-$(CONFIG_FRWU_DECODER)            += frwu.o
- OBJS-$(CONFIG_G2M_DECODER)             += g2meet.o
+ OBJS-$(CONFIG_G2M_DECODER)             += g2meet.o elsdec.o
  OBJS-$(CONFIG_G723_1_DECODER)          += g723_1.o acelp_vectors.o \
 -                                          celp_filters.o
 +                                          celp_filters.o celp_math.o
 +OBJS-$(CONFIG_G723_1_ENCODER)          += g723_1.o acelp_vectors.o celp_math.o
 +OBJS-$(CONFIG_G729_DECODER)            += g729dec.o lsp.o celp_math.o acelp_filters.o acelp_pitch_delay.o acelp_vectors.o g729postfilter.o
  OBJS-$(CONFIG_GIF_DECODER)             += gifdec.o lzw.o
  OBJS-$(CONFIG_GIF_ENCODER)             += gif.o lzwenc.o
  OBJS-$(CONFIG_GSM_DECODER)             += gsmdec.o gsmdec_data.o msgsmdec.o
index 0000000,5e89045..c4869c9
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,422 +1,422 @@@
 - * This file is part of Libav.
+ /*
+  * ELS (Entropy Logarithmic-Scale) decoder
+  *
+  * Copyright (c) 2013 Maxim Poliakovski
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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
+  */
+ /**
+  * @file
+  * Entropy Logarithmic-Scale binary arithmetic decoder
+  */
+ #include <math.h>
+ #include <stdint.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)
+ #define RUNG_SPACE          (64 * sizeof(ElsRungNode))
+ /* ELS coder tables. */
+ static const struct Ladder {
+     int8_t  AMps;
+     int8_t  ALps;
+     uint8_t next0;
+     uint8_t next1;
+ } Ladder[174] = {
+     { -6,   -5,   2,   1 },
+     { -2,  -12,   3,   6 },
+     { -2,  -12,   4,   6 },
+     { -1,  -16,   7,   5 },
+     { -1,  -16,   8,  10 },
+     { -5,   -6,  11,   9 },
+     { -6,   -5,  10,   5 },
+     { -1,  -18,  13,  11 },
+     { -1,  -18,  12,  14 },
+     { -6,   -5,  15,  18 },
+     { -5,   -6,  14,   9 },
+     { -3,   -8,  17,  15 },
+     { -1,  -20,  20,  16 },
+     { -1,  -20,  23,  17 },
+     { -3,   -8,  16,  18 },
+     { -5,   -6,  19,  26 },
+     { -3,   -9,  22,  24 },
+     { -3,   -9,  21,  19 },
+     { -5,   -6,  24,  26 },
+     { -4,   -7,  27,  25 },
+     { -1,  -22,  34,  28 },
+     { -2,  -11,  29,  27 },
+     { -2,  -11,  28,  30 },
+     { -1,  -22,  39,  29 },
+     { -4,   -7,  30,  32 },
+     { -6,   -5,  33,  31 },
+     { -6,   -5,  32,  25 },
+     { -3,   -8,  35,  33 },
+     { -2,  -12,  36,  38 },
+     { -2,  -12,  37,  35 },
+     { -3,   -8,  38,  40 },
+     { -6,   -5,  41,  48 },
+     { -6,   -5,  40,  31 },
+     { -5,   -6,  43,  41 },
+     { -1,  -24,  94,  42 },
+     { -3,   -8,  45,  43 },
+     { -2,  -12,  42,  44 },
+     { -2,  -12,  47,  45 },
+     { -3,   -8,  44,  46 },
+     { -1,  -24, 125,  47 },
+     { -5,   -6,  46,  48 },
+     { -6,   -5,  49,  49 },
+     { -2,  -13, 152, 164 },
+     { -4,   -7,  51,  49 },
+     { -3,   -9, 164, 168 },
+     { -3,   -9,  55,  51 },
+     { -4,   -7, 168, 170 },
+     { -2,  -13,  67,  55 },
+     { -6,   -5, 170,  49 },
+     { -6,   -5,  51, 170 },
+     { -1,  -72,  50,  74 },
+     { -4,   -7,  53,  49 },
+     { -1,  -61,  50,  74 },
+     { -3,   -8,  55,  49 },
+     { -1,  -51,  52,  76 },
+     { -3,   -9,  57,  51 },
+     { -1,  -46,  54,  76 },
+     { -2,  -10,  59,  53 },
+     { -1,  -43,  56,  78 },
+     { -2,  -11,  61,  53 },
+     { -1,  -41,  58,  80 },
+     { -2,  -12,  63,  55 },
+     { -1,  -39,  60,  82 },
+     { -2,  -12,  65,  55 },
+     { -1,  -37,  62,  84 },
+     { -2,  -13,  67,  57 },
+     { -1,  -36,  64,  86 },
+     { -1,  -14,  69,  59 },
+     { -1,  -35,  66,  88 },
+     { -1,  -14,  71,  59 },
+     { -1,  -34,  68,  90 },
+     { -1,  -15,  73,  61 },
+     { -1,  -33,  70,  92 },
+     { -1,  -15,  75,  61 },
+     { -1,  -32,  72,  94 },
+     { -1,  -15,  77,  63 },
+     { -1,  -31,  74,  96 },
+     { -1,  -16,  79,  65 },
+     { -1,  -31,  76,  98 },
+     { -1,  -16,  81,  67 },
+     { -1,  -30,  78, 100 },
+     { -1,  -17,  83,  67 },
+     { -1,  -29,  80, 102 },
+     { -1,  -17,  85,  69 },
+     { -1,  -29,  82, 104 },
+     { -1,  -18,  87,  71 },
+     { -1,  -28,  84, 104 },
+     { -1,  -18,  89,  73 },
+     { -1,  -28,  86, 108 },
+     { -1,  -18,  91,  73 },
+     { -1,  -27,  88, 108 },
+     { -1,  -19,  93,  75 },
+     { -1,  -27,  90, 112 },
+     { -1,  -19,  95,  77 },
+     { -1,  -26,  92, 112 },
+     { -1,  -20,  97,  79 },
+     { -1,  -26,  94, 114 },
+     { -1,  -20,  99,  81 },
+     { -1,  -25,  96, 116 },
+     { -1,  -20, 101,  83 },
+     { -1,  -25,  98, 118 },
+     { -1,  -21, 103,  83 },
+     { -1,  -24, 100, 120 },
+     { -1,  -21, 105,  85 },
+     { -1,  -24, 102, 122 },
+     { -1,  -22, 107,  87 },
+     { -1,  -23, 104, 124 },
+     { -1,  -22, 109,  89 },
+     { -1,  -23, 106, 126 },
+     { -1,  -22, 111,  91 },
+     { -1,  -22, 108, 128 },
+     { -1,  -23, 113,  93 },
+     { -1,  -22, 110, 130 },
+     { -1,  -23, 115,  95 },
+     { -1,  -22, 112, 132 },
+     { -1,  -24, 117,  97 },
+     { -1,  -21, 114, 134 },
+     { -1,  -24, 119,  99 },
+     { -1,  -21, 116, 136 },
+     { -1,  -25, 121, 101 },
+     { -1,  -20, 118, 136 },
+     { -1,  -25, 123, 103 },
+     { -1,  -20, 120, 138 },
+     { -1,  -26, 125, 105 },
+     { -1,  -20, 122, 140 },
+     { -1,  -26, 127, 107 },
+     { -1,  -19, 124, 142 },
+     { -1,  -27, 129, 107 },
+     { -1,  -19, 126, 144 },
+     { -1,  -27, 131, 111 },
+     { -1,  -18, 128, 146 },
+     { -1,  -28, 133, 111 },
+     { -1,  -18, 130, 146 },
+     { -1,  -28, 135, 115 },
+     { -1,  -18, 132, 148 },
+     { -1,  -29, 137, 115 },
+     { -1,  -17, 134, 150 },
+     { -1,  -29, 139, 117 },
+     { -1,  -17, 136, 152 },
+     { -1,  -30, 141, 119 },
+     { -1,  -16, 138, 152 },
+     { -1,  -31, 143, 121 },
+     { -1,  -16, 140, 154 },
+     { -1,  -31, 145, 123 },
+     { -1,  -15, 142, 156 },
+     { -1,  -32, 147, 125 },
+     { -1,  -15, 144, 158 },
+     { -1,  -33, 149, 127 },
+     { -1,  -15, 146, 158 },
+     { -1,  -34, 151, 129 },
+     { -1,  -14, 148, 160 },
+     { -1,  -35, 153, 131 },
+     { -1,  -14, 150, 160 },
+     { -1,  -36, 155, 133 },
+     { -2,  -13, 152, 162 },
+     { -1,  -37, 157, 135 },
+     { -2,  -12, 154, 164 },
+     { -1,  -39, 159, 137 },
+     { -2,  -12, 156, 164 },
+     { -1,  -41, 161, 139 },
+     { -2,  -11, 158, 166 },
+     { -1,  -43, 163, 141 },
+     { -2,  -10, 160, 166 },
+     { -1,  -46, 165, 143 },
+     { -3,   -9, 162, 168 },
+     { -1,  -51, 167, 143 },
+     { -3,   -8, 164, 170 },
+     { -1,  -61, 169, 145 },
+     { -4,   -7, 166, 170 },
+     { -1,  -72, 169, 145 },
+     { -6,   -5, 168,  49 },
+     {  0, -108, 171, 171 },
+     {  0, -108, 172, 172 },
+     { -6,   -5, 173, 173 },
+ };
+ static const uint32_t els_exp_tab[ELS_JOTS_PER_BYTE * 4 + 1] = {
+            0,        0,       0,       0,       0,       0,         0,        0,
+            0,        0,       0,       0,       0,       0,         0,        0,
+            0,        0,       0,       0,       0,       0,         0,        0,
+            0,        0,       0,       0,       0,       0,         0,        0,
+            0,        0,       0,       0,       1,       1,         1,        1,
+            1,        2,       2,       2,       3,       4,         4,        5,
+            6,        7,       8,      10,      11,      13,        16,       18,
+           21,       25,      29,      34,      40,      47,        54,       64,
+           74,       87,     101,     118,     138,      161,      188,      219,
+          256,      298,     348,     406,     474,      552,      645,      752,
+          877,     1024,    1194,    1393,    1625,     1896,     2211,     2580,
+         3010,     3511,    4096,    4778,    5573,     6501,     7584,     8847,
+        10321,    12040,   14045,   16384,   19112,    22295,    26007,    30339,
+        35391,    41285,   48160,   56180,   65536,    76288,    89088,   103936,
+       121344,   141312,  165120,  192512,  224512,   262144,   305664,   356608,
+       416000,   485376,  566016,  660480,  770560,   898816,  1048576,  1223168,
+      1426688,  1664256, 1941504, 2264832, 2642176,  3082240,  3595520,  4194304,
+      4892672,  5707520, 6657792, 7766784, 9060096, 10568960, 12328960, 14382080,
+     16777216,
+ };
+ void ff_els_decoder_init(ElsDecCtx *ctx, const uint8_t *in, size_t data_size)
+ {
+     int nbytes;
+     /* consume up to 3 bytes from the input data */
+     if (data_size >= 3) {
+         ctx->x = AV_RB24(in);
+         nbytes = 3;
+     } else if (data_size == 2) {
+         ctx->x = AV_RB16(in);
+         nbytes = 2;
+     } else {
+         ctx->x = *in;
+         nbytes = 1;
+     }
+     ctx->in_buf    = in + nbytes;
+     ctx->data_size = data_size - nbytes;
+     ctx->err       = 0;
+     ctx->j         = ELS_JOTS_PER_BYTE;
+     ctx->t         = ELS_MAX;
+     ctx->diff      = FFMIN(ELS_MAX - ctx->x,
+                            ELS_MAX - els_exp_tab[ELS_JOTS_PER_BYTE * 4 - 1]);
+ }
+ void ff_els_decoder_uninit(ElsUnsignedRung *rung)
+ {
+     av_free(rung->rem_rung_list);
+ }
+ static int els_import_byte(ElsDecCtx *ctx)
+ {
+     if (!ctx->data_size) {
+         ctx->err = AVERROR_EOF;
+         return AVERROR_EOF;
+     }
+     ctx->x   = (ctx->x << 8) | *ctx->in_buf++;
+     ctx->data_size--;
+     ctx->j  += ELS_JOTS_PER_BYTE;
+     ctx->t <<= 8;
+     return 0;
+ }
+ int ff_els_decode_bit(ElsDecCtx *ctx, uint8_t *rung)
+ {
+     int z, bit, ret;
+     const uint32_t *pAllowable = &els_exp_tab[ELS_JOTS_PER_BYTE * 3];
+     if (ctx->err)
+         return 0;
+     z          = pAllowable[ctx->j + Ladder[*rung].ALps];
+     ctx->t    -= z;
+     ctx->diff -= z;
+     if (ctx->diff > 0)
+         return *rung & 1;   /* shortcut for x < t > pAllowable[j - 1] */
+     if (ctx->t > ctx->x) {  /* decode most probable symbol (MPS) */
+         ctx->j += Ladder[*rung].AMps;
+         while (ctx->t > pAllowable[ctx->j])
+             ctx->j++;
+         if (ctx->j <= 0) { /* MPS: import one byte from bytestream. */
+             ret = els_import_byte(ctx);
+             if (ret < 0)
+                 return ret;
+         }
+         z     = ctx->t;
+         bit   = *rung & 1;
+         *rung = Ladder[*rung].next0;
+     } else { /* decode less probable symbol (LPS) */
+         ctx->x -= ctx->t;
+         ctx->t  = z;
+         ctx->j += Ladder[*rung].ALps;
+         if (ctx->j <= 0) {
+             /* LPS: import one byte from bytestream. */
+             z <<= 8;
+             ret = els_import_byte(ctx);
+             if (ret < 0)
+                 return ret;
+             if (ctx->j <= 0) {
+                 /* LPS: import second byte from bytestream. */
+                 z <<= 8;
+                 ret = els_import_byte(ctx);
+                 if (ret < 0)
+                     return ret;
+                 while (pAllowable[ctx->j - 1] >= z)
+                     ctx->j--;
+             }
+         }
+         bit   = !(*rung & 1);
+         *rung = Ladder[*rung].next1;
+     }
+     ctx->diff = FFMIN(z - ctx->x, z - pAllowable[ctx->j - 1]);
+     return bit;
+ }
+ unsigned ff_els_decode_unsigned(ElsDecCtx *ctx, ElsUnsignedRung *ur)
+ {
+     int i, n, r, bit;
+     ElsRungNode *rung_node;
+     if (ctx->err)
+         return 0;
+     /* decode unary prefix */
+     for (n = 0; n < ELS_EXPGOLOMB_LEN + 1; n++)
+         if (ff_els_decode_bit(ctx, &ur->prefix_rung[n]))
+             break;
+     /* handle the error/overflow case */
+     if (ctx->err || n >= ELS_EXPGOLOMB_LEN) {
+         ctx->err = AVERROR(EOVERFLOW);
+         return 0;
+     }
+     /* handle the zero case */
+     if (!n)
+         return 0;
+     /* initialize probability tree */
+     if (!ur->rem_rung_list) {
+         ur->rem_rung_list = av_realloc(NULL, RUNG_SPACE);
+         if (!ur->rem_rung_list) {
+             ctx->err = AVERROR(ENOMEM);
+             return 0;
+         }
+         memset(ur->rem_rung_list, 0, RUNG_SPACE);
+         ur->rung_list_size = RUNG_SPACE;
+         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
+                     ptrdiff_t pos     = rung_node - ur->rem_rung_list;
+                     ur->rem_rung_list = av_realloc(ur->rem_rung_list,
+                                                    ur->rung_list_size +
+                                                    RUNG_SPACE);
+                     if (!ur->rem_rung_list) {
+                         av_free(ur->rem_rung_list);
+                         ctx->err = AVERROR(ENOMEM);
+                         return 0;
+                     }
+                     memset((uint8_t *) ur->rem_rung_list + ur->rung_list_size, 0,
+                            RUNG_SPACE);
+                     ur->rung_list_size += RUNG_SPACE;
+                     // 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)
+             return bit;
+         r = (r << 1) + bit;
+     }
+     return (1 << n) - 1 + r; /* make value from exp golomb code */
+ }
index 0000000,515b49a..139a24a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,60 +1,60 @@@
 - * This file is part of Libav.
+ /*
+  * ELS (Entropy Logarithmic-Scale) decoder
+  *
+  * Copyright (c) 2013 Maxim Poliakovski
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * 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.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * 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
+  */
+ /**
+  * @file
+  * Entropy Logarithmic-Scale binary arithmetic coder
+  */
+ #ifndef AVCODEC_ELSDEC_H
+ #define AVCODEC_ELSDEC_H
+ #include <stdint.h>
+ #include <sys/types.h>
+ #define ELS_EXPGOLOMB_LEN   10
+ typedef struct ElsDecCtx {
+     const uint8_t *in_buf;
+     unsigned x;
+     size_t data_size;
+     int j, t, diff, err;
+ } ElsDecCtx;
+ typedef struct ElsRungNode {
+     uint8_t  rung;
+     uint16_t next_index;
+ } ElsRungNode;
+ typedef struct ElsUnsignedRung {
+     uint8_t      prefix_rung[ELS_EXPGOLOMB_LEN + 1];
+     ElsRungNode  *rem_rung_list;
+     size_t       rung_list_size;
+     uint16_t     avail_index;
+ } ElsUnsignedRung;
+ void ff_els_decoder_init(ElsDecCtx *ctx, const uint8_t *in, size_t data_size);
+ void ff_els_decoder_uninit(ElsUnsignedRung *rung);
+ int  ff_els_decode_bit(ElsDecCtx *ctx, unsigned char *rung);
+ unsigned ff_els_decode_unsigned(ElsDecCtx *ctx, ElsUnsignedRung *ur);
+ #endif /* AVCODEC_ELSDEC_H */
@@@ -1,10 -1,11 +1,11 @@@
  /*
-  * Go2Webinar decoder
+  * Go2Webinar / Go2Meeting decoder
   * Copyright (c) 2012 Konstantin Shishkov
+  * Copyright (c) 2013 Maxim Poliakovski
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
@@@ -318,7 -362,660 +363,660 @@@ static int jpg_decode_data(JPGContext *
      return 0;
  }
  
 -static void kempf_restore_buf(const uint8_t *src, int len,
+ #define LOAD_NEIGHBOURS(x)      \
+     W   = curr_row[(x)   - 1];  \
+     N   = above_row[(x)];       \
+     WW  = curr_row[(x)   - 2];  \
+     NW  = above_row[(x)  - 1];  \
+     NE  = above_row[(x)  + 1];  \
+     NN  = above2_row[(x)];      \
+     NNW = above2_row[(x) - 1];  \
+     NWW = above_row[(x)  - 2];  \
+     NNE = above2_row[(x) + 1]
+ #define UPDATE_NEIGHBOURS(x)    \
+     NNW = NN;                   \
+     NN  = NNE;                  \
+     NWW = NW;                   \
+     NW  = N;                    \
+     N   = NE;                   \
+     NE  = above_row[(x)  + 1];  \
+     NNE = above2_row[(x) + 1]
+ #define R_shift 16
+ #define G_shift  8
+ #define B_shift  0
+ static inline int log2_ceil(uint32_t x)
+ {
+     int c = 0;
+     for (--x; x > 0; x >>= 1)
+         c++;
+     return c;
+ }
+ /* improved djb2 hash from http://www.cse.yorku.ca/~oz/hash.html */
+ static int djb2_hash(uint32_t key)
+ {
+     int h = 5381;
+     h = (h * 33) ^ ((key >> 24) & 0xFF); // xxx: probably not needed at all
+     h = (h * 33) ^ ((key >> 16) & 0xFF);
+     h = (h * 33) ^ ((key >>  8) & 0xFF);
+     h = (h * 33) ^  (key        & 0xFF);
+     return h & (EPIC_HASH_SIZE - 1);
+ }
+ static void epic_hash_init(ePICPixHash *hash)
+ {
+     memset(hash, 0, sizeof(*hash));
+ }
+ static ePICPixHashElem *epic_hash_find(const ePICPixHash *hash, uint32_t key)
+ {
+     int i, idx = djb2_hash(key);
+     ePICPixHashElem *bucket = hash->bucket[idx];
+     for (i = 0; i < hash->bucket_fill[idx]; i++)
+         if (bucket[i].pix_id == key)
+             return &bucket[i];
+     return NULL;
+ }
+ static ePICPixHashElem *epic_hash_add(ePICPixHash *hash, uint32_t key)
+ {
+     ePICPixHashElem *bucket, *ret;
+     int idx = djb2_hash(key);
+     if (hash->bucket_size[idx] > INT_MAX / sizeof(**hash->bucket))
+         return NULL;
+     if (!(hash->bucket_fill[idx] < hash->bucket_size[idx])) {
+         int new_size = hash->bucket_size[idx] + 16;
+         bucket = av_realloc(hash->bucket[idx], new_size * sizeof(*bucket));
+         if (!bucket)
+             return NULL;
+         hash->bucket[idx]      = bucket;
+         hash->bucket_size[idx] = new_size;
+     }
+     ret = &hash->bucket[idx][hash->bucket_fill[idx]++];
+     memset(ret, 0, sizeof(*ret));
+     ret->pix_id = key;
+     return ret;
+ }
+ static int epic_add_pixel_to_cache(ePICPixHash *hash, uint32_t key, uint32_t pix)
+ {
+     ePICPixListElem *new_elem;
+     ePICPixHashElem *hash_elem = epic_hash_find(hash, key);
+     if (!hash_elem) {
+         if (!(hash_elem = epic_hash_add(hash, key)))
+             return AVERROR(ENOMEM);
+     }
+     new_elem = av_mallocz(sizeof(*new_elem));
+     if (!new_elem)
+         return AVERROR(ENOMEM);
+     new_elem->pixel = pix;
+     new_elem->next  = hash_elem->list;
+     hash_elem->list = new_elem;
+     return 0;
+ }
+ static inline int epic_cache_entries_for_pixel(const ePICPixHash *hash,
+                                                uint32_t pix)
+ {
+     ePICPixHashElem *hash_elem = epic_hash_find(hash, pix);
+     if (hash_elem != NULL && hash_elem->list != NULL)
+         return 1;
+     return 0;
+ }
+ static void epic_free_pixel_cache(ePICPixHash *hash)
+ {
+     int i, j;
+     for (i = 0; i < EPIC_HASH_SIZE; i++) {
+         for (j = 0; j < hash->bucket_fill[i]; j++) {
+             ePICPixListElem *list_elem = hash->bucket[i][j].list;
+             while (list_elem) {
+                 ePICPixListElem *tmp = list_elem->next;
+                 av_free(list_elem);
+                 list_elem = tmp;
+             }
+         }
+         av_freep(&hash->bucket[i]);
+         hash->bucket_size[i] =
+         hash->bucket_fill[i] = 0;
+     }
+ }
+ static inline int is_pixel_on_stack(const ePICContext *dc, uint32_t pix)
+ {
+     int i;
+     for (i = 0; i < dc->stack_pos; i++)
+         if (dc->stack[i] == pix)
+             break;
+     return i != dc->stack_pos;
+ }
+ #define TOSIGNED(val) (((val) >> 1) ^ -((val) & 1))
+ static inline int epic_decode_component_pred(ePICContext *dc,
+                                              int N, int W, int NW)
+ {
+     unsigned delta = ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung);
+     return mid_pred(N, N + W - NW, W) - TOSIGNED(delta);
+ }
+ static uint32_t epic_decode_pixel_pred(ePICContext *dc, int x, int y,
+                                        const uint32_t *curr_row,
+                                        const uint32_t *above_row)
+ {
+     uint32_t N, W, NW, pred;
+     unsigned delta;
+     int GN, GW, GNW, R, G, B;
+     if (x && y) {
+         W  = curr_row[x  - 1];
+         N  = above_row[x];
+         NW = above_row[x - 1];
+         GN  = (N  >> G_shift) & 0xFF;
+         GW  = (W  >> G_shift) & 0xFF;
+         GNW = (NW >> G_shift) & 0xFF;
+         G = epic_decode_component_pred(dc, GN, GW, GNW);
+         R = G + epic_decode_component_pred(dc,
+                                            ((N  >> R_shift) & 0xFF) - GN,
+                                            ((W  >> R_shift) & 0xFF) - GW,
+                                            ((NW >> R_shift) & 0xFF) - GNW);
+         B = G + epic_decode_component_pred(dc,
+                                            ((N  >> B_shift) & 0xFF) - GN,
+                                            ((W  >> B_shift) & 0xFF) - GW,
+                                            ((NW >> B_shift) & 0xFF) - GNW);
+     } else {
+         if (x)
+             pred = curr_row[x - 1];
+         else
+             pred = above_row[x];
+         delta = ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung);
+         R     = ((pred >> R_shift) & 0xFF) - TOSIGNED(delta);
+         delta = ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung);
+         G     = ((pred >> G_shift) & 0xFF) - TOSIGNED(delta);
+         delta = ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung);
+         B     = ((pred >> B_shift) & 0xFF) - TOSIGNED(delta);
+     }
+     return (R << R_shift) | (G << G_shift) | (B << B_shift);
+ }
+ static int epic_predict_pixel(ePICContext *dc, uint8_t *rung,
+                               uint32_t *pPix, uint32_t pix)
+ {
+     if (!ff_els_decode_bit(&dc->els_ctx, rung)) {
+         *pPix = pix;
+         return 1;
+     }
+     dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = pix;
+     return 0;
+ }
+ static int epic_handle_edges(ePICContext *dc, int x, int y,
+                              const uint32_t *curr_row,
+                              const uint32_t *above_row, uint32_t *pPix)
+ {
+     uint32_t pix;
+     if (!x && !y) { /* special case: top-left pixel */
+         /* the top-left pixel is coded independently with 3 unsigned numbers */
+         *pPix = (ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung) << R_shift) |
+                 (ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung) << G_shift) |
+                 (ff_els_decode_unsigned(&dc->els_ctx, &dc->unsigned_rung) << B_shift);
+         return 1;
+     }
+     if (x) { /* predict from W first */
+         pix = curr_row[x - 1];
+         if (epic_predict_pixel(dc, &dc->W_flag_rung, pPix, pix))
+             return 1;
+     }
+     if (y) { /* then try to predict from N */
+         pix = above_row[x];
+         if (!dc->stack_pos || dc->stack[0] != pix) {
+             if (epic_predict_pixel(dc, &dc->N_flag_rung, pPix, pix))
+                 return 1;
+         }
+     }
+     return 0;
+ }
+ static int epic_decode_run_length(ePICContext *dc, int x, int y, int tile_width,
+                                   const uint32_t *curr_row,
+                                   const uint32_t *above_row,
+                                   const uint32_t *above2_row,
+                                   uint32_t *pPix, int *pRun)
+ {
+     int idx, got_pixel = 0, WWneW, old_WWneW = 0;
+     uint32_t W, WW, N, NN, NW, NE, NWW, NNW, NNE;
+     *pRun = 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++ & EPIC_PIX_STACK_MAX] = W;
+     else {
+         *pPix     = W;
+         got_pixel = 1;
+     }
+     do {
+         int NWneW = 1;
+         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:
+                 break; // do nothing here
+             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);
+                     if (!ff_els_decode_bit(&dc->els_ctx, &dc->N_ctx_rung[idx])) {
+                         NWneW = 0;
+                         *pPix = N;
+                         got_pixel = 1;
+                         break;
+                     }
+                 }
+                 /* fall through */
+             default:
+                 NWneW = 1;
+                 old_WWneW = WWneW;
+                 if (!is_pixel_on_stack(dc, N))
+                     dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = N;
+             }
+         }
+         (*pRun)++;
+         if (x + *pRun >= tile_width - 1)
+             break;
+         UPDATE_NEIGHBOURS(x + *pRun);
+         if (!NWneW && NW == N && N == NE) {
+             int pos, run, rle;
+             int start_pos = x + *pRun;
+             /* scan for a run of pix in the line above */
+             uint32_t pix = above_row[start_pos + 1];
+             for (pos = start_pos + 2; pos < tile_width; pos++)
+                 if (!(above_row[pos] == pix))
+                     break;
+             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 {
+                 int flag;
+                 /* 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_predict_pixel2(ePICContext *dc, uint8_t *rung,
+                                uint32_t *pPix, uint32_t pix)
+ {
+     if (ff_els_decode_bit(&dc->els_ctx, rung)) {
+         *pPix = pix;
+         return 1;
+     }
+     dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = pix;
+     return 0;
+ }
+ static int epic_predict_from_NW_NE(ePICContext *dc, int x, int y, int run,
+                                    int tile_width, const uint32_t *curr_row,
+                                    const uint32_t *above_row, uint32_t *pPix)
+ {
+     int pos;
+     /* try to reuse the NW pixel first */
+     if (x && y) {
+         uint32_t NW = above_row[x - 1];
+         if (NW != curr_row[x - 1] && NW != above_row[x] && !is_pixel_on_stack(dc, NW)) {
+             if (epic_predict_pixel2(dc, &dc->nw_pred_rung[NW & 0xFF], pPix, NW))
+                 return 1;
+         }
+     }
+     /* try to reuse the NE[x + run, y] pixel */
+     pos = x + run - 1;
+     if (pos < tile_width - 1 && y) {
+         uint32_t NE = above_row[pos + 1];
+         if (NE != above_row[pos] && !is_pixel_on_stack(dc, NE)) {
+             if (epic_predict_pixel2(dc, &dc->ne_pred_rung[NE & 0xFF], pPix, NE))
+                 return 1;
+         }
+     }
+     return 0;
+ }
+ static int epic_decode_from_cache(ePICContext *dc, uint32_t W, uint32_t *pPix)
+ {
+     ePICPixListElem *list, *prev = NULL;
+     ePICPixHashElem *hash_elem = epic_hash_find(&dc->hash, W);
+     if (!hash_elem || !hash_elem->list)
+         return 0;
+     list = hash_elem->list;
+     while (list) {
+         if (!is_pixel_on_stack(dc, list->pixel)) {
+             if (ff_els_decode_bit(&dc->els_ctx, &list->rung)) {
+                 *pPix = list->pixel;
+                 if (list != hash_elem->list) {
+                     prev->next      = list->next;
+                     list->next      = hash_elem->list;
+                     hash_elem->list = list;
+                 }
+                 return 1;
+             }
+             dc->stack[dc->stack_pos++ & EPIC_PIX_STACK_MAX] = list->pixel;
+         }
+         prev = list;
+         list = list->next;
+     }
+     return 0;
+ }
+ static int epic_decode_tile(ePICContext *dc, uint8_t *out, int tile_height,
+                             int tile_width, int stride)
+ {
+     int x, y;
+     uint32_t pix;
+     uint32_t *curr_row = NULL, *above_row = NULL, *above2_row;
+     for (y = 0; y < tile_height; y++, out += stride) {
+         above2_row = above_row;
+         above_row  = curr_row;
+         curr_row   = (uint32_t *) out;
+         for (x = 0, dc->next_run_pos = 0; x < tile_width;) {
+             if (dc->els_ctx.err)
+                 return AVERROR_INVALIDDATA; // bail out in the case of ELS overflow
+             pix = curr_row[x - 1]; // get W pixel
+             if (y >= 1 && x >= 2 &&
+                 pix != curr_row[x - 2]  && pix != above_row[x - 1] &&
+                 pix != above_row[x - 2] && pix != above_row[x] &&
+                 !epic_cache_entries_for_pixel(&dc->hash, pix)) {
+                 curr_row[x] = epic_decode_pixel_pred(dc, x, y, curr_row, above_row);
+                 x++;
+             } else {
+                 int got_pixel, run;
+                 dc->stack_pos = 0; // empty stack
+                 if (y < 2 || x < 2 || x == tile_width - 1) {
+                     run       = 1;
+                     got_pixel = epic_handle_edges(dc, x, y, curr_row, above_row, &pix);
+                 } else
+                     got_pixel = epic_decode_run_length(dc, x, y, tile_width,
+                                                        curr_row, above_row,
+                                                        above2_row, &pix, &run);
+                 if (!got_pixel && !epic_predict_from_NW_NE(dc, x, y, run,
+                                                            tile_width, curr_row,
+                                                            above_row, &pix)) {
+                     uint32_t ref_pix = curr_row[x - 1];
+                     if (!x || !epic_decode_from_cache(dc, ref_pix, &pix)) {
+                         pix = epic_decode_pixel_pred(dc, x, y, curr_row, above_row);
+                         if (x) {
+                             int ret = epic_add_pixel_to_cache(&dc->hash,
+                                                               ref_pix,
+                                                               pix);
+                             if (ret)
+                                 return ret;
+                         }
+                     }
+                 }
+                 for (; run > 0; x++, run--)
+                     curr_row[x] = pix;
+             }
+         }
+     }
+     return 0;
+ }
+ static int epic_jb_decode_tile(G2MContext *c, int tile_x, int tile_y,
+                                const uint8_t *src, size_t src_size,
+                                AVCodecContext *avctx)
+ {
+     uint8_t prefix, mask = 0x80;
+     int extrabytes, tile_width, tile_height, awidth, aheight;
+     size_t els_dsize;
+     uint8_t *dst;
+     if (!src_size)
+         return 0;
+     /* get data size of the ELS partition as unsigned variable-length integer */
+     prefix = *src++;
+     src_size--;
+     for (extrabytes = 0; (prefix & mask) && (extrabytes < 7); extrabytes++)
+         mask >>= 1;
+     if (extrabytes > 3 || src_size < extrabytes) {
+         av_log(avctx, AV_LOG_ERROR, "ePIC: invalid data size VLI\n");
+         return AVERROR_INVALIDDATA;
+     }
+     els_dsize = prefix & ((0x80 >> extrabytes) - 1); // mask out the length prefix
+     while (extrabytes-- > 0) {
+         els_dsize = (els_dsize << 8) | *src++;
+         src_size--;
+     }
+     if (src_size < els_dsize) {
+         av_log(avctx, AV_LOG_ERROR, "ePIC: data too short, needed %zu, got %zu\n",
+                els_dsize, src_size);
+         return AVERROR_INVALIDDATA;
+     }
+     tile_width  = FFMIN(c->width  - tile_x * c->tile_width,  c->tile_width);
+     tile_height = FFMIN(c->height - tile_y * c->tile_height, c->tile_height);
+     awidth      = FFALIGN(tile_width,  16);
+     aheight     = FFALIGN(tile_height, 16);
+     if (els_dsize) {
+         int ret, i, j, k;
+         uint8_t tr_r, tr_g, tr_b, *buf;
+         uint32_t *in;
+         /* ELS decoder initializations */
+         memset(&c->ec, 0, sizeof(c->ec));
+         ff_els_decoder_init(&c->ec.els_ctx, src, els_dsize);
+         epic_hash_init(&c->ec.hash);
+         /* decode transparent pixel value */
+         tr_r = ff_els_decode_unsigned(&c->ec.els_ctx, &c->ec.unsigned_rung);
+         tr_g = ff_els_decode_unsigned(&c->ec.els_ctx, &c->ec.unsigned_rung);
+         tr_b = ff_els_decode_unsigned(&c->ec.els_ctx, &c->ec.unsigned_rung);
+         if (c->ec.els_ctx.err != 0) {
+             av_log(avctx, AV_LOG_ERROR,
+                    "ePIC: couldn't decode transparency pixel!\n");
+             return AVERROR_INVALIDDATA;
+         }
+         ret = epic_decode_tile(&c->ec, c->epic_buf, tile_height, tile_width,
+                                c->epic_buf_stride);
+         epic_free_pixel_cache(&c->ec.hash);
+         ff_els_decoder_uninit(&c->ec.unsigned_rung);
+         if (ret) {
+             av_log(avctx, AV_LOG_ERROR,
+                    "ePIC: tile decoding failed, frame=%d, tile_x=%d, tile_y=%d\n",
+                    avctx->frame_number, tile_x, tile_y);
+             return AVERROR_INVALIDDATA;
+         }
+         buf = c->epic_buf;
+         dst = c->framebuf + tile_x * c->tile_width * 3 +
+               tile_y * c->tile_height * c->framebuf_stride;
+         for (j = 0; j < tile_height; j++) {
+             uint8_t *out = dst;
+             in  = (uint32_t *) buf;
+             for (i = 0; i < tile_width; i++) {
+                 out[0] = (in[i] >> R_shift) & 0xFF;
+                 out[1] = (in[i] >> G_shift) & 0xFF;
+                 out[2] = (in[i] >> B_shift) & 0xFF;
+                 out   += 3;
+             }
+             buf += c->epic_buf_stride;
+             dst += c->framebuf_stride;
+         }
+         if (src_size > els_dsize) {
+             uint8_t *jpg;
+             uint32_t tr;
+             int bstride = FFALIGN(tile_width, 16) >> 3;
+             int nblocks = 0;
+             int estride = c->epic_buf_stride >> 2;
+             src      += els_dsize;
+             src_size -= els_dsize;
+             in = (uint32_t *) c->epic_buf;
+             tr = (tr_r << R_shift) | (tr_g << G_shift) | (tr_b << B_shift);
+             memset(c->kempf_flags, 0,
+                    (aheight >> 3) * bstride * sizeof(*c->kempf_flags));
+             for (j = 0; j < tile_height; j += 8) {
+                 for (i = 0; i < tile_width; i += 8) {
+                     c->kempf_flags[(i >> 3) + (j >> 3) * bstride] = 0;
+                     for (k = 0; k < 8 * 8; k++) {
+                         if (in[i + (k & 7) + (k >> 3) * estride] == tr) {
+                             c->kempf_flags[(i >> 3) + (j >> 3) * bstride] = 1;
+                             nblocks++;
+                             break;
+                         }
+                     }
+                 }
+                 in += 8 * estride;
+             }
+             memset(c->jpeg_tile, 0, c->tile_stride * aheight);
+             jpg_decode_data(&c->jc, awidth, aheight, src, src_size,
+                             c->jpeg_tile, c->tile_stride,
+                             c->kempf_flags, bstride, nblocks, c->swapuv);
+             in  = (uint32_t *) c->epic_buf;
+             dst = c->framebuf + tile_x * c->tile_width * 3 +
+                   tile_y * c->tile_height * c->framebuf_stride;
+             jpg = c->jpeg_tile;
+             for (j = 0; j < tile_height; j++) {
+                 for (i = 0; i < tile_width; i++)
+                     if (in[i] == tr)
+                         memcpy(dst + i * 3, jpg + i * 3, 3);
+                 in  += c->epic_buf_stride >> 2;
+                 dst += c->framebuf_stride;
+                 jpg += c->tile_stride;
+             }
+         }
+     } else {
+         dst = c->framebuf + tile_x * c->tile_width * 3 +
+               tile_y * c->tile_height * c->framebuf_stride;
+         return jpg_decode_data(&c->jc, tile_width, tile_height, src, src_size,
+                                dst, c->framebuf_stride, NULL, 0, 0, c->swapuv);
+     }
+     return 0;
+ }
 +static int kempf_restore_buf(const uint8_t *src, int len,
                                uint8_t *dst, int stride,
                                const uint8_t *jpeg_tile, int tile_stride,
                                int width, int height,
  {
      GetBitContext gb;
      int i, j, nb, col;
 +    int ret;
+     int align_width = FFALIGN(width, 16);
  
 -    init_get_bits(&gb, src, len * 8);
 +    if ((ret = init_get_bits8(&gb, src, len)) < 0)
 +        return ret;
  
      if (npal <= 2)       nb = 1;
      else if (npal <= 4)  nb = 2;
              else
                  memcpy(dst + i * 3, jpeg_tile + i * 3, 3);
          }
+         skip_bits_long(&gb, nb * (align_width - width));
      }
 +
 +    return 0;
  }
  
  static int kempf_decode_tile(G2MContext *c, int tile_x, int tile_y,
@@@ -475,10 -1166,12 +1175,12 @@@ static int g2m_init_buffers(G2MContext 
              return AVERROR(ENOMEM);
      }
      if (!c->synth_tile || !c->jpeg_tile ||
+         (c->compression == 2 && !c->epic_buf_base) ||
          c->old_tile_w < c->tile_width ||
          c->old_tile_h < c->tile_height) {
-         c->tile_stride = FFALIGN(c->tile_width, 16) * 3;
-         aligned_height = FFALIGN(c->tile_height,    16);
 -        c->tile_stride     = FFALIGN(c->tile_width * 3, 16);
++        c->tile_stride     = FFALIGN(c->tile_width, 16) * 3;
+         c->epic_buf_stride = FFALIGN(c->tile_width * 4, 16);
+         aligned_height     = FFALIGN(c->tile_height,    16);
          av_free(c->synth_tile);
          av_free(c->jpeg_tile);
          av_free(c->kempf_buf);
@@@ -29,8 -29,8 +29,8 @@@
  #include "libavutil/version.h"
  
  #define LIBAVCODEC_VERSION_MAJOR 56
- #define LIBAVCODEC_VERSION_MINOR  45
- #define LIBAVCODEC_VERSION_MICRO 102
 -#define LIBAVCODEC_VERSION_MINOR 31
 -#define LIBAVCODEC_VERSION_MICRO  0
++#define LIBAVCODEC_VERSION_MINOR  46
++#define LIBAVCODEC_VERSION_MICRO 100
  
  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                 LIBAVCODEC_VERSION_MINOR, \