Merge commit '08c2d8f0aa679c2f060721d1d0d4f33d2ae32368'
* commit '08c2d8f0aa679c2f060721d1d0d4f33d2ae32368': Go2Meeting decoder Conflicts: Changelog libavcodec/g2meet.c libavcodec/version.h Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
commit
68939f7682
@ -11,6 +11,7 @@ version <next>:
|
|||||||
- rewritten ASF demuxer
|
- rewritten ASF demuxer
|
||||||
- showvolume filter
|
- showvolume filter
|
||||||
- Many improvements to the JPEG 2000 decoder
|
- Many improvements to the JPEG 2000 decoder
|
||||||
|
- Go2Meeting decoding support
|
||||||
|
|
||||||
|
|
||||||
version 2.7:
|
version 2.7:
|
||||||
|
@ -667,6 +667,8 @@ following image formats are supported:
|
|||||||
@tab Sorenson H.263 used in Flash
|
@tab Sorenson H.263 used in Flash
|
||||||
@item Forward Uncompressed @tab @tab X
|
@item Forward Uncompressed @tab @tab X
|
||||||
@item Fraps @tab @tab X
|
@item Fraps @tab @tab X
|
||||||
|
@item Go2Meeting @tab @tab X
|
||||||
|
@tab fourcc: G2M2, G2M3
|
||||||
@item Go2Webinar @tab @tab X
|
@item Go2Webinar @tab @tab X
|
||||||
@tab fourcc: G2M4
|
@tab fourcc: G2M4
|
||||||
@item H.261 @tab X @tab X
|
@item H.261 @tab X @tab X
|
||||||
|
@ -257,7 +257,7 @@ OBJS-$(CONFIG_FLIC_DECODER) += flicvideo.o
|
|||||||
OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o
|
OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o
|
||||||
OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o
|
OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o
|
||||||
OBJS-$(CONFIG_FRWU_DECODER) += frwu.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 \
|
OBJS-$(CONFIG_G723_1_DECODER) += g723_1.o acelp_vectors.o \
|
||||||
celp_filters.o celp_math.o
|
celp_filters.o celp_math.o
|
||||||
OBJS-$(CONFIG_G723_1_ENCODER) += g723_1.o acelp_vectors.o celp_math.o
|
OBJS-$(CONFIG_G723_1_ENCODER) += g723_1.o acelp_vectors.o celp_math.o
|
||||||
|
422
libavcodec/elsdec.c
Normal file
422
libavcodec/elsdec.c
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
/*
|
||||||
|
* ELS (Entropy Logarithmic-Scale) decoder
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Maxim Poliakovski
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 */
|
||||||
|
}
|
60
libavcodec/elsdec.h
Normal file
60
libavcodec/elsdec.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* ELS (Entropy Logarithmic-Scale) decoder
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Maxim Poliakovski
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Go2Webinar decoder
|
* Go2Webinar / Go2Meeting decoder
|
||||||
* Copyright (c) 2012 Konstantin Shishkov
|
* Copyright (c) 2012 Konstantin Shishkov
|
||||||
|
* Copyright (c) 2013 Maxim Poliakovski
|
||||||
*
|
*
|
||||||
* This file is part of FFmpeg.
|
* This file is part of FFmpeg.
|
||||||
*
|
*
|
||||||
@ -21,7 +22,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* Go2Webinar decoder
|
* Go2Webinar / Go2Meeting decoder
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@ -32,12 +33,16 @@
|
|||||||
#include "avcodec.h"
|
#include "avcodec.h"
|
||||||
#include "blockdsp.h"
|
#include "blockdsp.h"
|
||||||
#include "bytestream.h"
|
#include "bytestream.h"
|
||||||
|
#include "elsdec.h"
|
||||||
#include "get_bits.h"
|
#include "get_bits.h"
|
||||||
#include "idctdsp.h"
|
#include "idctdsp.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "jpegtables.h"
|
#include "jpegtables.h"
|
||||||
#include "mjpeg.h"
|
#include "mjpeg.h"
|
||||||
|
|
||||||
|
#define EPIC_PIX_STACK_SIZE 1024
|
||||||
|
#define EPIC_PIX_STACK_MAX (EPIC_PIX_STACK_SIZE - 1)
|
||||||
|
|
||||||
enum ChunkType {
|
enum ChunkType {
|
||||||
DISPLAY_INFO = 0xC8,
|
DISPLAY_INFO = 0xC8,
|
||||||
TILE_DATA,
|
TILE_DATA,
|
||||||
@ -74,6 +79,42 @@ static const uint8_t chroma_quant[64] = {
|
|||||||
50, 50, 50, 50, 50, 50, 50, 50,
|
50, 50, 50, 50, 50, 50, 50, 50,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct ePICPixListElem {
|
||||||
|
struct ePICPixListElem *next;
|
||||||
|
uint32_t pixel;
|
||||||
|
uint8_t rung;
|
||||||
|
} ePICPixListElem;
|
||||||
|
|
||||||
|
typedef struct ePICPixHashElem {
|
||||||
|
uint32_t pix_id;
|
||||||
|
struct ePICPixListElem *list;
|
||||||
|
} ePICPixHashElem;
|
||||||
|
|
||||||
|
#define EPIC_HASH_SIZE 256
|
||||||
|
typedef struct ePICPixHash {
|
||||||
|
ePICPixHashElem *bucket[EPIC_HASH_SIZE];
|
||||||
|
int bucket_size[EPIC_HASH_SIZE];
|
||||||
|
int bucket_fill[EPIC_HASH_SIZE];
|
||||||
|
} ePICPixHash;
|
||||||
|
|
||||||
|
typedef struct ePICContext {
|
||||||
|
ElsDecCtx els_ctx;
|
||||||
|
int next_run_pos;
|
||||||
|
ElsUnsignedRung unsigned_rung;
|
||||||
|
uint8_t W_flag_rung;
|
||||||
|
uint8_t N_flag_rung;
|
||||||
|
uint8_t W_ctx_rung[256];
|
||||||
|
uint8_t N_ctx_rung[512];
|
||||||
|
uint8_t nw_pred_rung[256];
|
||||||
|
uint8_t ne_pred_rung[256];
|
||||||
|
uint8_t prev_row_rung[14];
|
||||||
|
uint8_t runlen_zeroes[14];
|
||||||
|
uint8_t runlen_one;
|
||||||
|
int stack_pos;
|
||||||
|
uint32_t stack[EPIC_PIX_STACK_SIZE];
|
||||||
|
ePICPixHash hash;
|
||||||
|
} ePICContext;
|
||||||
|
|
||||||
typedef struct JPGContext {
|
typedef struct JPGContext {
|
||||||
BlockDSPContext bdsp;
|
BlockDSPContext bdsp;
|
||||||
IDCTDSPContext idsp;
|
IDCTDSPContext idsp;
|
||||||
@ -87,7 +128,9 @@ typedef struct JPGContext {
|
|||||||
} JPGContext;
|
} JPGContext;
|
||||||
|
|
||||||
typedef struct G2MContext {
|
typedef struct G2MContext {
|
||||||
|
ePICContext ec;
|
||||||
JPGContext jc;
|
JPGContext jc;
|
||||||
|
|
||||||
int version;
|
int version;
|
||||||
|
|
||||||
int compression;
|
int compression;
|
||||||
@ -101,8 +144,9 @@ typedef struct G2MContext {
|
|||||||
uint8_t *framebuf;
|
uint8_t *framebuf;
|
||||||
int framebuf_stride, old_width, old_height;
|
int framebuf_stride, old_width, old_height;
|
||||||
|
|
||||||
uint8_t *synth_tile, *jpeg_tile;
|
uint8_t *synth_tile, *jpeg_tile, *epic_buf, *epic_buf_base;
|
||||||
int tile_stride, old_tile_w, old_tile_h;
|
int tile_stride, epic_buf_stride, old_tile_w, old_tile_h;
|
||||||
|
int swapuv;
|
||||||
|
|
||||||
uint8_t *kempf_buf, *kempf_flags;
|
uint8_t *kempf_buf, *kempf_flags;
|
||||||
|
|
||||||
@ -229,11 +273,11 @@ static int jpg_decode_block(JPGContext *c, GetBitContext *gb,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void yuv2rgb(uint8_t *out, int Y, int U, int V)
|
static inline void yuv2rgb(uint8_t *out, int ridx, int Y, int U, int V)
|
||||||
{
|
{
|
||||||
out[0] = av_clip_uint8(Y + ( 91881 * V + 32768 >> 16));
|
out[ridx] = av_clip_uint8(Y + (91881 * V + 32768 >> 16));
|
||||||
out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16));
|
out[1] = av_clip_uint8(Y + (-22554 * U - 46802 * V + 32768 >> 16));
|
||||||
out[2] = av_clip_uint8(Y + (116130 * U + 32768 >> 16));
|
out[2 - ridx] = av_clip_uint8(Y + (116130 * U + 32768 >> 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int jpg_decode_data(JPGContext *c, int width, int height,
|
static int jpg_decode_data(JPGContext *c, int width, int height,
|
||||||
@ -247,6 +291,7 @@ static int jpg_decode_data(JPGContext *c, int width, int height,
|
|||||||
int bx, by;
|
int bx, by;
|
||||||
int unesc_size;
|
int unesc_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
const int ridx = swapuv ? 2 : 0;
|
||||||
|
|
||||||
if ((ret = av_reallocp(&c->buf,
|
if ((ret = av_reallocp(&c->buf,
|
||||||
src_size + FF_INPUT_BUFFER_PADDING_SIZE)) < 0)
|
src_size + FF_INPUT_BUFFER_PADDING_SIZE)) < 0)
|
||||||
@ -299,9 +344,9 @@ static int jpg_decode_data(JPGContext *c, int width, int height,
|
|||||||
int Y, U, V;
|
int Y, U, V;
|
||||||
|
|
||||||
Y = c->block[(j >> 3) * 2 + (i >> 3)][(i & 7) + (j & 7) * 8];
|
Y = c->block[(j >> 3) * 2 + (i >> 3)][(i & 7) + (j & 7) * 8];
|
||||||
U = c->block[4 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128;
|
U = c->block[4][(i >> 1) + (j >> 1) * 8] - 128;
|
||||||
V = c->block[5 ^ swapuv][(i >> 1) + (j >> 1) * 8] - 128;
|
V = c->block[5][(i >> 1) + (j >> 1) * 8] - 128;
|
||||||
yuv2rgb(out + i * 3, Y, U, V);
|
yuv2rgb(out + i * 3, ridx, Y, U, V);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,6 +363,659 @@ static int jpg_decode_data(JPGContext *c, int width, int height,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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,
|
static int kempf_restore_buf(const uint8_t *src, int len,
|
||||||
uint8_t *dst, int stride,
|
uint8_t *dst, int stride,
|
||||||
const uint8_t *jpeg_tile, int tile_stride,
|
const uint8_t *jpeg_tile, int tile_stride,
|
||||||
@ -327,6 +1025,7 @@ static int kempf_restore_buf(const uint8_t *src, int len,
|
|||||||
GetBitContext gb;
|
GetBitContext gb;
|
||||||
int i, j, nb, col;
|
int i, j, nb, col;
|
||||||
int ret;
|
int ret;
|
||||||
|
int align_width = FFALIGN(width, 16);
|
||||||
|
|
||||||
if ((ret = init_get_bits8(&gb, src, len)) < 0)
|
if ((ret = init_get_bits8(&gb, src, len)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
@ -346,6 +1045,7 @@ static int kempf_restore_buf(const uint8_t *src, int len,
|
|||||||
else
|
else
|
||||||
memcpy(dst + i * 3, jpeg_tile + i * 3, 3);
|
memcpy(dst + i * 3, jpeg_tile + i * 3, 3);
|
||||||
}
|
}
|
||||||
|
skip_bits_long(&gb, nb * (align_width - width));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -475,22 +1175,31 @@ static int g2m_init_buffers(G2MContext *c)
|
|||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
}
|
}
|
||||||
if (!c->synth_tile || !c->jpeg_tile ||
|
if (!c->synth_tile || !c->jpeg_tile ||
|
||||||
|
(c->compression == 2 && !c->epic_buf_base) ||
|
||||||
c->old_tile_w < c->tile_width ||
|
c->old_tile_w < c->tile_width ||
|
||||||
c->old_tile_h < c->tile_height) {
|
c->old_tile_h < c->tile_height) {
|
||||||
c->tile_stride = FFALIGN(c->tile_width, 16) * 3;
|
c->tile_stride = FFALIGN(c->tile_width, 16) * 3;
|
||||||
aligned_height = FFALIGN(c->tile_height, 16);
|
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->synth_tile);
|
||||||
av_free(c->jpeg_tile);
|
av_free(c->jpeg_tile);
|
||||||
av_free(c->kempf_buf);
|
av_free(c->kempf_buf);
|
||||||
av_free(c->kempf_flags);
|
av_free(c->kempf_flags);
|
||||||
|
av_free(c->epic_buf_base);
|
||||||
c->synth_tile = av_mallocz(c->tile_stride * aligned_height);
|
c->synth_tile = av_mallocz(c->tile_stride * aligned_height);
|
||||||
c->jpeg_tile = av_mallocz(c->tile_stride * aligned_height);
|
c->jpeg_tile = av_mallocz(c->tile_stride * aligned_height);
|
||||||
c->kempf_buf = av_mallocz((c->tile_width + 1) * aligned_height
|
c->kempf_buf = av_mallocz((c->tile_width + 1) * aligned_height +
|
||||||
+ FF_INPUT_BUFFER_PADDING_SIZE);
|
FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
c->kempf_flags = av_mallocz( c->tile_width * aligned_height);
|
c->kempf_flags = av_mallocz(c->tile_width * aligned_height);
|
||||||
if (!c->synth_tile || !c->jpeg_tile ||
|
if (!c->synth_tile || !c->jpeg_tile ||
|
||||||
!c->kempf_buf || !c->kempf_flags)
|
!c->kempf_buf || !c->kempf_flags)
|
||||||
return AVERROR(ENOMEM);
|
return AVERROR(ENOMEM);
|
||||||
|
if (c->compression == 2) {
|
||||||
|
c->epic_buf_base = av_mallocz(c->epic_buf_stride * aligned_height + 4);
|
||||||
|
if (!c->epic_buf_base)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
c->epic_buf = c->epic_buf_base + 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -696,10 +1405,7 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
return AVERROR_INVALIDDATA;
|
return AVERROR_INVALIDDATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((magic & 0xF) < 4) {
|
c->swapuv = magic == MKBETAG('G', '2', 'M', '2');
|
||||||
av_log(avctx, AV_LOG_ERROR, "G2M2 and G2M3 are not yet supported\n");
|
|
||||||
return AVERROR(ENOSYS);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (bytestream2_get_bytes_left(&bc) > 5) {
|
while (bytestream2_get_bytes_left(&bc) > 5) {
|
||||||
chunk_size = bytestream2_get_le32(&bc) - 1;
|
chunk_size = bytestream2_get_le32(&bc) - 1;
|
||||||
@ -808,9 +1514,10 @@ static int g2m_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
switch (c->compression) {
|
switch (c->compression) {
|
||||||
case COMPR_EPIC_J_B:
|
case COMPR_EPIC_J_B:
|
||||||
av_log(avctx, AV_LOG_ERROR,
|
ret = epic_jb_decode_tile(c, c->tile_x, c->tile_y,
|
||||||
"ePIC j-b compression is not implemented yet\n");
|
buf + bytestream2_tell(&bc),
|
||||||
return AVERROR(ENOSYS);
|
chunk_size - 2, avctx);
|
||||||
|
break;
|
||||||
case COMPR_KEMPF_J_B:
|
case COMPR_KEMPF_J_B:
|
||||||
ret = kempf_decode_tile(c, c->tile_x, c->tile_y,
|
ret = kempf_decode_tile(c, c->tile_x, c->tile_y,
|
||||||
buf + bytestream2_tell(&bc),
|
buf + bytestream2_tell(&bc),
|
||||||
@ -906,6 +1613,7 @@ static av_cold int g2m_decode_end(AVCodecContext *avctx)
|
|||||||
|
|
||||||
jpg_free_context(&c->jc);
|
jpg_free_context(&c->jc);
|
||||||
|
|
||||||
|
av_freep(&c->epic_buf_base);
|
||||||
av_freep(&c->kempf_buf);
|
av_freep(&c->kempf_buf);
|
||||||
av_freep(&c->kempf_flags);
|
av_freep(&c->kempf_flags);
|
||||||
av_freep(&c->synth_tile);
|
av_freep(&c->synth_tile);
|
||||||
@ -926,4 +1634,5 @@ AVCodec ff_g2m_decoder = {
|
|||||||
.close = g2m_decode_end,
|
.close = g2m_decode_end,
|
||||||
.decode = g2m_decode_frame,
|
.decode = g2m_decode_frame,
|
||||||
.capabilities = CODEC_CAP_DR1,
|
.capabilities = CODEC_CAP_DR1,
|
||||||
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE,
|
||||||
};
|
};
|
||||||
|
@ -29,8 +29,8 @@
|
|||||||
#include "libavutil/version.h"
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MAJOR 56
|
#define LIBAVCODEC_VERSION_MAJOR 56
|
||||||
#define LIBAVCODEC_VERSION_MINOR 45
|
#define LIBAVCODEC_VERSION_MINOR 46
|
||||||
#define LIBAVCODEC_VERSION_MICRO 102
|
#define LIBAVCODEC_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
LIBAVCODEC_VERSION_MINOR, \
|
LIBAVCODEC_VERSION_MINOR, \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user