/*
* huffyuv decoder
*
- * Copyright (c) 2002-2003 Michael Niedermayer <michaelni@gmx.at>
+ * Copyright (c) 2002-2014 Michael Niedermayer <michaelni@gmx.at>
*
* see http://www.pcisys.net/~melanson/codecs/huffyuv.txt for a description of
* the algorithm used
int p, i, y, u;
for (p = 0; p < 4; p++) {
int p0 = s->version > 2 ? p : 0;
- for (i = y = 0; y < s->n; y++) {
+ for (i = y = 0; y < s->vlc_n; y++) {
int len0 = s->len[p0][y];
int limit = VLC_BITS - len0;
if(limit <= 0 || !len0)
continue;
- for (u = 0; u < s->n; u++) {
+ if((sign_extend(y, 8) & (s->vlc_n-1)) != y)
+ continue;
+ for (u = 0; u < s->vlc_n; u++) {
int len1 = s->len[p][u];
if (len1 > limit || !len1)
continue;
+ if((sign_extend(u, 8) & (s->vlc_n-1)) != u)
+ continue;
av_assert0(i < (1 << VLC_BITS));
len[i] = len0 + len1;
bits[i] = (s->bits[p0][y] << len1) + s->bits[p][u];
- symbols[i] = (y << 8) + u; //FIXME
+ symbols[i] = (y << 8) + (u & 0xFF);
if(symbols[i] != 0xffff) // reserved to mean "invalid"
i++;
}
count = 1 + s->alpha + 2*s->chroma;
for (i = 0; i < count; i++) {
- if (read_len_table(s->len[i], &gb, s->n) < 0)
+ if (read_len_table(s->len[i], &gb, s->vlc_n) < 0)
return -1;
- if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->n) < 0) {
+ if (ff_huffyuv_generate_bits_table(s->bits[i], s->len[i], s->vlc_n) < 0) {
return -1;
}
ff_free_vlc(&s->vlc[i]);
- if ((ret = init_vlc(&s->vlc[i], VLC_BITS, s->n, s->len[i], 1, 1,
+ if ((ret = init_vlc(&s->vlc[i], VLC_BITS, s->vlc_n, s->len[i], 1, 1,
s->bits[i], 4, 4, 0)) < 0)
return ret;
}
{
HYuvContext *s = avctx->priv_data;
- ff_huffyuv_common_init(avctx);
memset(s->vlc, 0, 4 * sizeof(VLC));
- s->interlaced = s->height > 288;
+ s->interlaced = avctx->height > 288;
s->bgr32 = 1;
s->bps = 8;
s->n = 1<<s->bps;
+ s->vlc_n = FFMIN(s->n, MAX_VLC_N);
s->chroma = 1;
if (s->version >= 2) {
int method, interlace;
} else {
s->bps = (avctx->extradata[1] >> 4) + 1;
s->n = 1<<s->bps;
+ s->vlc_n = FFMIN(s->n, MAX_VLC_N);
s->chroma_h_shift = avctx->extradata[1] & 3;
s->chroma_v_shift = (avctx->extradata[1] >> 2) & 3;
s->yuv = !!(((uint8_t*)avctx->extradata)[2] & 1);
s->yuv = 1;
break;
case 24:
- case 32:
if (s->bgr32) {
- avctx->pix_fmt = AV_PIX_FMT_RGB32;
- s->alpha = 1;
+ avctx->pix_fmt = AV_PIX_FMT_0RGB32;
} else {
avctx->pix_fmt = AV_PIX_FMT_BGR24;
}
break;
+ case 32:
+ av_assert0(s->bgr32);
+ avctx->pix_fmt = AV_PIX_FMT_RGB32;
+ s->alpha = 1;
+ break;
default:
return AVERROR_INVALIDDATA;
}
case 0x070:
avctx->pix_fmt = AV_PIX_FMT_GRAY8;
break;
+ case 0x0F0:
+ avctx->pix_fmt = AV_PIX_FMT_GRAY16;
+ break;
case 0x170:
avctx->pix_fmt = AV_PIX_FMT_GRAY8A;
break;
case 0x470:
avctx->pix_fmt = AV_PIX_FMT_GBRP;
break;
+ case 0x480:
+ avctx->pix_fmt = AV_PIX_FMT_GBRP9;
+ break;
+ case 0x490:
+ avctx->pix_fmt = AV_PIX_FMT_GBRP10;
+ break;
+ case 0x4B0:
+ avctx->pix_fmt = AV_PIX_FMT_GBRP12;
+ break;
+ case 0x4D0:
+ avctx->pix_fmt = AV_PIX_FMT_GBRP14;
+ break;
+ case 0x4F0:
+ avctx->pix_fmt = AV_PIX_FMT_GBRP16;
+ break;
case 0x570:
avctx->pix_fmt = AV_PIX_FMT_GBRAP;
break;
case 0x6D0:
avctx->pix_fmt = AV_PIX_FMT_YUV444P14;
break;
+ case 0x6F0:
+ avctx->pix_fmt = AV_PIX_FMT_YUV444P16;
+ break;
case 0x671:
avctx->pix_fmt = AV_PIX_FMT_YUV422P;
break;
case 0x6D1:
avctx->pix_fmt = AV_PIX_FMT_YUV422P14;
break;
+ case 0x6F1:
+ avctx->pix_fmt = AV_PIX_FMT_YUV422P16;
+ break;
case 0x672:
avctx->pix_fmt = AV_PIX_FMT_YUV411P;
break;
case 0x6D5:
avctx->pix_fmt = AV_PIX_FMT_YUV420P14;
break;
+ case 0x6F5:
+ avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
+ break;
case 0x67A:
avctx->pix_fmt = AV_PIX_FMT_YUV410P;
break;
case 0x790:
avctx->pix_fmt = AV_PIX_FMT_YUVA444P10;
break;
+ case 0x7F0:
+ avctx->pix_fmt = AV_PIX_FMT_YUVA444P16;
+ break;
case 0x771:
avctx->pix_fmt = AV_PIX_FMT_YUVA422P;
break;
case 0x791:
avctx->pix_fmt = AV_PIX_FMT_YUVA422P10;
break;
+ case 0x7F1:
+ avctx->pix_fmt = AV_PIX_FMT_YUVA422P16;
+ break;
case 0x775:
avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
break;
case 0x795:
avctx->pix_fmt = AV_PIX_FMT_YUVA420P10;
break;
+ case 0x7F5:
+ avctx->pix_fmt = AV_PIX_FMT_YUVA420P16;
+ break;
default:
return AVERROR_INVALIDDATA;
}
}
+ ff_huffyuv_common_init(avctx);
if ((avctx->pix_fmt == AV_PIX_FMT_YUV422P || avctx->pix_fmt == AV_PIX_FMT_YUV420P) && avctx->width & 1) {
av_log(avctx, AV_LOG_ERROR, "width must be even for this colorspace\n");
dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
}\
}
+#define READ_2PIX_PLANE14(dst0, dst1, plane){\
+ int16_t code = get_vlc2(&s->gb, s->vlc[4+plane].table, VLC_BITS, 1);\
+ if(code != (int16_t)0xffff){\
+ dst0 = code>>8;\
+ dst1 = sign_extend(code, 8);\
+ }else{\
+ dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
+ dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
+ }\
+}
+
#define READ_2PIX_PLANE16(dst0, dst1, plane){\
- dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
- dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3);\
+ dst0 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;\
+ dst0 += get_bits(&s->gb, 2);\
+ dst1 = get_vlc2(&s->gb, s->vlc[plane].table, VLC_BITS, 3)<<2;\
+ dst1 += get_bits(&s->gb, 2);\
}
static void decode_plane_bitstream(HYuvContext *s, int count, int plane)
{
READ_2PIX_PLANE(s->temp[0][2 * i], s->temp[0][2 * i + 1], plane);
}
}
+ } else if (s->bps <= 14) {
+ if (count >= (get_bits_left(&s->gb)) / (31 * 2)) {
+ for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {
+ READ_2PIX_PLANE14(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane);
+ }
+ } else {
+ for(i=0; i<count; i++){
+ READ_2PIX_PLANE14(s->temp16[0][2 * i], s->temp16[0][2 * i + 1], plane);
+ }
+ }
} else {
if (count >= (get_bits_left(&s->gb)) / (31 * 2)) {
for (i = 0; i < count && get_bits_left(&s->gb) > 0; i++) {