Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e75056bc54 | ||
|
8755a7890e | ||
|
d0688fdd31 | ||
|
0e05292a6c | ||
|
23f228a0d0 | ||
|
110aff4b24 | ||
|
4a1c3df592 | ||
|
185abfb218 | ||
|
280590e338 | ||
|
9767ea7aa7 | ||
|
771ceb19f2 | ||
|
7739947671 | ||
|
8abf1d882e | ||
|
1a53095406 | ||
|
60eebf5c12 | ||
|
30ee6c1995 |
16
Changelog
16
Changelog
@@ -2,6 +2,22 @@ Entries are sorted chronologically from oldest to youngest within each release,
|
|||||||
releases are sorted from youngest to oldest.
|
releases are sorted from youngest to oldest.
|
||||||
|
|
||||||
|
|
||||||
|
version 0.5.6:
|
||||||
|
- svq1dec: call avcodec_set_dimensions() after dimensions changed. (NGS00148, CVE-2011-4579)
|
||||||
|
- vmd: fix segfaults on corruped streams (CVE-2011-4364)
|
||||||
|
- commits related to CVE-2011-4353:
|
||||||
|
- vp6: partially propagate huffman tree building errors during coeff model parsing and fix misspelling
|
||||||
|
- Plug some memory leaks in the VP6 decoder
|
||||||
|
- vp6: Reset the internal state when aborting key frames header parsing
|
||||||
|
- vp6: Fix illegal read.
|
||||||
|
- vp6: Fix illegal read.
|
||||||
|
- Fix out of bound reads in the QDM2 decoder.
|
||||||
|
- commits related to CVE-2011-4351:
|
||||||
|
- Check for out of bound writes in the QDM2 decoder.
|
||||||
|
- qdm2: check output buffer size before decoding
|
||||||
|
- Fix qdm2 decoder packet handling to match the api
|
||||||
|
|
||||||
|
|
||||||
version 0.5.5:
|
version 0.5.5:
|
||||||
|
|
||||||
- Fix memory (re)allocation in matroskadec.c (MSVR11-011/CVE-2011-3504)
|
- Fix memory (re)allocation in matroskadec.c (MSVR11-011/CVE-2011-3504)
|
||||||
|
17
RELEASE
17
RELEASE
@@ -163,3 +163,20 @@ General notes
|
|||||||
This maintenance-only release addresses several security issues that
|
This maintenance-only release addresses several security issues that
|
||||||
were brought to our attention.
|
were brought to our attention.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* 0.5.7 Dec 25, 2011
|
||||||
|
|
||||||
|
General notes
|
||||||
|
-------------
|
||||||
|
|
||||||
|
This maintenance-only release addresses several security issues that
|
||||||
|
were brought to our attention. In details, it features fixes for the
|
||||||
|
QDM2 decoder (CVE-2011-4351), DoS in the VP5/VP6 decoders
|
||||||
|
(CVE-2011-4353), and a buffer overflow in the Sierra VMD decoder
|
||||||
|
CVE-2011-4364, and a safety fix in the SVQ1 decoder (CVE-2011-4579).
|
||||||
|
CVE-2011-4352, a bug in the VP3 decoder, is not known to affect this
|
||||||
|
release.
|
||||||
|
|
||||||
|
Distributors and system integrators are encouraged to update and share
|
||||||
|
their patches against this branch.
|
||||||
|
@@ -1378,6 +1378,8 @@ static void qdm2_fft_decode_tones (QDM2Context *q, int duration, GetBitContext *
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
local_int_14 = (offset >> local_int_8);
|
local_int_14 = (offset >> local_int_8);
|
||||||
|
if (local_int_14 >= FF_ARRAY_ELEMS(fft_level_index_table))
|
||||||
|
return;
|
||||||
|
|
||||||
if (q->nb_channels > 1) {
|
if (q->nb_channels > 1) {
|
||||||
channel = get_bits1(gb);
|
channel = get_bits1(gb);
|
||||||
@@ -1912,7 +1914,7 @@ static av_cold int qdm2_decode_close(AVCodecContext *avctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
|
static int qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
|
||||||
{
|
{
|
||||||
int ch, i;
|
int ch, i;
|
||||||
const int frame_size = (q->frame_size * q->channels);
|
const int frame_size = (q->frame_size * q->channels);
|
||||||
@@ -1951,7 +1953,7 @@ static void qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
|
|||||||
|
|
||||||
if (!q->has_errors && q->sub_packet_list_C[0].packet != NULL) {
|
if (!q->has_errors && q->sub_packet_list_C[0].packet != NULL) {
|
||||||
SAMPLES_NEEDED_2("has errors, and C list is not empty")
|
SAMPLES_NEEDED_2("has errors, and C list is not empty")
|
||||||
return;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1972,6 +1974,8 @@ static void qdm2_decode (QDM2Context *q, const uint8_t *in, int16_t *out)
|
|||||||
|
|
||||||
out[i] = value;
|
out[i] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1980,25 +1984,33 @@ static int qdm2_decode_frame(AVCodecContext *avctx,
|
|||||||
const uint8_t *buf, int buf_size)
|
const uint8_t *buf, int buf_size)
|
||||||
{
|
{
|
||||||
QDM2Context *s = avctx->priv_data;
|
QDM2Context *s = avctx->priv_data;
|
||||||
|
int16_t *out = data;
|
||||||
|
int i, out_size;
|
||||||
|
|
||||||
if(!buf)
|
if(!buf)
|
||||||
return 0;
|
return 0;
|
||||||
if(buf_size < s->checksum_size)
|
if(buf_size < s->checksum_size)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*data_size = s->channels * s->frame_size * sizeof(int16_t);
|
out_size = 16 * s->channels * s->frame_size *
|
||||||
|
av_get_bits_per_sample_format(avctx->sample_fmt)/8;
|
||||||
|
if (*data_size < out_size) {
|
||||||
|
av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n");
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
av_log(avctx, AV_LOG_DEBUG, "decode(%d): %p[%d] -> %p[%d]\n",
|
av_log(avctx, AV_LOG_DEBUG, "decode(%d): %p[%d] -> %p[%d]\n",
|
||||||
buf_size, buf, s->checksum_size, data, *data_size);
|
buf_size, buf, s->checksum_size, data, *data_size);
|
||||||
|
|
||||||
qdm2_decode(s, buf, data);
|
for (i = 0; i < 16; i++) {
|
||||||
|
if (qdm2_decode(s, buf, out) < 0)
|
||||||
// reading only when next superblock found
|
return -1;
|
||||||
if (s->sub_packet == 0) {
|
out += s->channels * s->frame_size;
|
||||||
return s->checksum_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
*data_size = out_size;
|
||||||
|
|
||||||
|
return buf_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
AVCodec qdm2_decoder =
|
AVCodec qdm2_decoder =
|
||||||
|
@@ -73,9 +73,11 @@ typedef struct VmdVideoContext {
|
|||||||
#define QUEUE_SIZE 0x1000
|
#define QUEUE_SIZE 0x1000
|
||||||
#define QUEUE_MASK 0x0FFF
|
#define QUEUE_MASK 0x0FFF
|
||||||
|
|
||||||
static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_len)
|
static void lz_unpack(const unsigned char *src, int src_len,
|
||||||
|
unsigned char *dest, int dest_len)
|
||||||
{
|
{
|
||||||
const unsigned char *s;
|
const unsigned char *s;
|
||||||
|
unsigned int s_len;
|
||||||
unsigned char *d;
|
unsigned char *d;
|
||||||
unsigned char *d_end;
|
unsigned char *d_end;
|
||||||
unsigned char queue[QUEUE_SIZE];
|
unsigned char queue[QUEUE_SIZE];
|
||||||
@@ -88,13 +90,16 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le
|
|||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
s = src;
|
s = src;
|
||||||
|
s_len = src_len;
|
||||||
d = dest;
|
d = dest;
|
||||||
d_end = d + dest_len;
|
d_end = d + dest_len;
|
||||||
dataleft = AV_RL32(s);
|
dataleft = AV_RL32(s);
|
||||||
s += 4;
|
s += 4; s_len -= 4;
|
||||||
memset(queue, 0x20, QUEUE_SIZE);
|
memset(queue, 0x20, QUEUE_SIZE);
|
||||||
|
if (s_len < 4)
|
||||||
|
return;
|
||||||
if (AV_RL32(s) == 0x56781234) {
|
if (AV_RL32(s) == 0x56781234) {
|
||||||
s += 4;
|
s += 4; s_len -= 4;
|
||||||
qpos = 0x111;
|
qpos = 0x111;
|
||||||
speclen = 0xF + 3;
|
speclen = 0xF + 3;
|
||||||
} else {
|
} else {
|
||||||
@@ -102,32 +107,41 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le
|
|||||||
speclen = 100; /* no speclen */
|
speclen = 100; /* no speclen */
|
||||||
}
|
}
|
||||||
|
|
||||||
while (dataleft > 0) {
|
while (dataleft > 0 && s_len > 0) {
|
||||||
tag = *s++;
|
tag = *s++; s_len--;
|
||||||
if ((tag == 0xFF) && (dataleft > 8)) {
|
if ((tag == 0xFF) && (dataleft > 8)) {
|
||||||
if (d + 8 > d_end)
|
if (d + 8 > d_end || s_len < 8)
|
||||||
return;
|
return;
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
queue[qpos++] = *d++ = *s++;
|
queue[qpos++] = *d++ = *s++;
|
||||||
qpos &= QUEUE_MASK;
|
qpos &= QUEUE_MASK;
|
||||||
}
|
}
|
||||||
|
s_len -= 8;
|
||||||
dataleft -= 8;
|
dataleft -= 8;
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
if (dataleft == 0)
|
if (dataleft == 0)
|
||||||
break;
|
break;
|
||||||
if (tag & 0x01) {
|
if (tag & 0x01) {
|
||||||
if (d + 1 > d_end)
|
if (d + 1 > d_end || s_len < 1)
|
||||||
return;
|
return;
|
||||||
queue[qpos++] = *d++ = *s++;
|
queue[qpos++] = *d++ = *s++;
|
||||||
qpos &= QUEUE_MASK;
|
qpos &= QUEUE_MASK;
|
||||||
dataleft--;
|
dataleft--;
|
||||||
|
s_len--;
|
||||||
} else {
|
} else {
|
||||||
|
if (s_len < 2)
|
||||||
|
return;
|
||||||
chainofs = *s++;
|
chainofs = *s++;
|
||||||
chainofs |= ((*s & 0xF0) << 4);
|
chainofs |= ((*s & 0xF0) << 4);
|
||||||
chainlen = (*s++ & 0x0F) + 3;
|
chainlen = (*s++ & 0x0F) + 3;
|
||||||
if (chainlen == speclen)
|
s_len -= 2;
|
||||||
|
if (chainlen == speclen) {
|
||||||
|
if (s_len < 1)
|
||||||
|
return;
|
||||||
chainlen = *s++ + 0xF + 3;
|
chainlen = *s++ + 0xF + 3;
|
||||||
|
s_len--;
|
||||||
|
}
|
||||||
if (d + chainlen > d_end)
|
if (d + chainlen > d_end)
|
||||||
return;
|
return;
|
||||||
for (j = 0; j < chainlen; j++) {
|
for (j = 0; j < chainlen; j++) {
|
||||||
@@ -144,7 +158,7 @@ static void lz_unpack(const unsigned char *src, unsigned char *dest, int dest_le
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int rle_unpack(const unsigned char *src, unsigned char *dest,
|
static int rle_unpack(const unsigned char *src, unsigned char *dest,
|
||||||
int src_len, int dest_len)
|
int src_count, int src_size, int dest_len)
|
||||||
{
|
{
|
||||||
const unsigned char *ps;
|
const unsigned char *ps;
|
||||||
unsigned char *pd;
|
unsigned char *pd;
|
||||||
@@ -153,31 +167,40 @@ static int rle_unpack(const unsigned char *src, unsigned char *dest,
|
|||||||
|
|
||||||
ps = src;
|
ps = src;
|
||||||
pd = dest;
|
pd = dest;
|
||||||
if (src_len & 1)
|
if (src_count & 1) {
|
||||||
|
if (src_size < 1)
|
||||||
|
return 0;
|
||||||
*pd++ = *ps++;
|
*pd++ = *ps++;
|
||||||
|
src_size--;
|
||||||
|
}
|
||||||
|
|
||||||
src_len >>= 1;
|
src_count >>= 1;
|
||||||
i = 0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
|
if (src_size < 1)
|
||||||
|
break;
|
||||||
l = *ps++;
|
l = *ps++;
|
||||||
|
src_size--;
|
||||||
if (l & 0x80) {
|
if (l & 0x80) {
|
||||||
l = (l & 0x7F) * 2;
|
l = (l & 0x7F) * 2;
|
||||||
if (pd + l > dest_end)
|
if (pd + l > dest_end || src_size < l)
|
||||||
return ps - src;
|
return ps - src;
|
||||||
memcpy(pd, ps, l);
|
memcpy(pd, ps, l);
|
||||||
ps += l;
|
ps += l;
|
||||||
|
src_size -= l;
|
||||||
pd += l;
|
pd += l;
|
||||||
} else {
|
} else {
|
||||||
if (pd + i > dest_end)
|
if (pd + i > dest_end || src_size < 2)
|
||||||
return ps - src;
|
return ps - src;
|
||||||
for (i = 0; i < l; i++) {
|
for (i = 0; i < l; i++) {
|
||||||
*pd++ = ps[0];
|
*pd++ = ps[0];
|
||||||
*pd++ = ps[1];
|
*pd++ = ps[1];
|
||||||
}
|
}
|
||||||
ps += 2;
|
ps += 2;
|
||||||
|
src_size -= 2;
|
||||||
}
|
}
|
||||||
i += l;
|
i += l;
|
||||||
} while (i < src_len);
|
} while (i < src_count);
|
||||||
|
|
||||||
return ps - src;
|
return ps - src;
|
||||||
}
|
}
|
||||||
@@ -192,6 +215,7 @@ static void vmd_decode(VmdVideoContext *s)
|
|||||||
const unsigned char *p = s->buf + 16;
|
const unsigned char *p = s->buf + 16;
|
||||||
|
|
||||||
const unsigned char *pb;
|
const unsigned char *pb;
|
||||||
|
unsigned int pb_size;
|
||||||
unsigned char meth;
|
unsigned char meth;
|
||||||
unsigned char *dp; /* pointer to current frame */
|
unsigned char *dp; /* pointer to current frame */
|
||||||
unsigned char *pp; /* pointer to previous frame */
|
unsigned char *pp; /* pointer to previous frame */
|
||||||
@@ -228,8 +252,9 @@ static void vmd_decode(VmdVideoContext *s)
|
|||||||
|
|
||||||
/* if only a certain region will be updated, copy the entire previous
|
/* if only a certain region will be updated, copy the entire previous
|
||||||
* frame before the decode */
|
* frame before the decode */
|
||||||
if (frame_x || frame_y || (frame_width != s->avctx->width) ||
|
if (s->prev_frame.data[0] &&
|
||||||
(frame_height != s->avctx->height)) {
|
(frame_x || frame_y || (frame_width != s->avctx->width) ||
|
||||||
|
(frame_height != s->avctx->height))) {
|
||||||
|
|
||||||
memcpy(s->frame.data[0], s->prev_frame.data[0],
|
memcpy(s->frame.data[0], s->prev_frame.data[0],
|
||||||
s->avctx->height * s->frame.linesize[0]);
|
s->avctx->height * s->frame.linesize[0]);
|
||||||
@@ -247,14 +272,19 @@ static void vmd_decode(VmdVideoContext *s)
|
|||||||
}
|
}
|
||||||
s->size -= (256 * 3 + 2);
|
s->size -= (256 * 3 + 2);
|
||||||
}
|
}
|
||||||
if (s->size >= 0) {
|
if (s->size > 0) {
|
||||||
/* originally UnpackFrame in VAG's code */
|
/* originally UnpackFrame in VAG's code */
|
||||||
pb = p;
|
pb = p;
|
||||||
meth = *pb++;
|
pb_size = s->buf + s->size - pb;
|
||||||
|
if (pb_size < 1)
|
||||||
|
return;
|
||||||
|
meth = *pb++; pb_size--;
|
||||||
if (meth & 0x80) {
|
if (meth & 0x80) {
|
||||||
lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
|
lz_unpack(pb, pb_size,
|
||||||
|
s->unpack_buffer, s->unpack_buffer_size);
|
||||||
meth &= 0x7F;
|
meth &= 0x7F;
|
||||||
pb = s->unpack_buffer;
|
pb = s->unpack_buffer;
|
||||||
|
pb_size = s->unpack_buffer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
|
dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
|
||||||
@@ -265,17 +295,21 @@ static void vmd_decode(VmdVideoContext *s)
|
|||||||
for (i = 0; i < frame_height; i++) {
|
for (i = 0; i < frame_height; i++) {
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
do {
|
do {
|
||||||
|
if (pb_size < 1)
|
||||||
|
return;
|
||||||
len = *pb++;
|
len = *pb++;
|
||||||
|
pb_size--;
|
||||||
if (len & 0x80) {
|
if (len & 0x80) {
|
||||||
len = (len & 0x7F) + 1;
|
len = (len & 0x7F) + 1;
|
||||||
if (ofs + len > frame_width)
|
if (ofs + len > frame_width || pb_size < len)
|
||||||
return;
|
return;
|
||||||
memcpy(&dp[ofs], pb, len);
|
memcpy(&dp[ofs], pb, len);
|
||||||
pb += len;
|
pb += len;
|
||||||
|
pb_size -= len;
|
||||||
ofs += len;
|
ofs += len;
|
||||||
} else {
|
} else {
|
||||||
/* interframe pixel copy */
|
/* interframe pixel copy */
|
||||||
if (ofs + len + 1 > frame_width)
|
if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
|
||||||
return;
|
return;
|
||||||
memcpy(&dp[ofs], &pp[ofs], len + 1);
|
memcpy(&dp[ofs], &pp[ofs], len + 1);
|
||||||
ofs += len + 1;
|
ofs += len + 1;
|
||||||
@@ -293,8 +327,11 @@ static void vmd_decode(VmdVideoContext *s)
|
|||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
for (i = 0; i < frame_height; i++) {
|
for (i = 0; i < frame_height; i++) {
|
||||||
|
if (pb_size < frame_width)
|
||||||
|
return;
|
||||||
memcpy(dp, pb, frame_width);
|
memcpy(dp, pb, frame_width);
|
||||||
pb += frame_width;
|
pb += frame_width;
|
||||||
|
pb_size -= frame_width;
|
||||||
dp += s->frame.linesize[0];
|
dp += s->frame.linesize[0];
|
||||||
pp += s->prev_frame.linesize[0];
|
pp += s->prev_frame.linesize[0];
|
||||||
}
|
}
|
||||||
@@ -304,18 +341,27 @@ static void vmd_decode(VmdVideoContext *s)
|
|||||||
for (i = 0; i < frame_height; i++) {
|
for (i = 0; i < frame_height; i++) {
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
do {
|
do {
|
||||||
|
if (pb_size < 1)
|
||||||
|
return;
|
||||||
len = *pb++;
|
len = *pb++;
|
||||||
|
pb_size--;
|
||||||
if (len & 0x80) {
|
if (len & 0x80) {
|
||||||
len = (len & 0x7F) + 1;
|
len = (len & 0x7F) + 1;
|
||||||
|
if (pb_size < 1)
|
||||||
|
return;
|
||||||
if (*pb++ == 0xFF)
|
if (*pb++ == 0xFF)
|
||||||
len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
|
len = rle_unpack(pb, &dp[ofs], len, pb_size, frame_width - ofs);
|
||||||
else
|
else {
|
||||||
|
if (pb_size < len)
|
||||||
|
return;
|
||||||
memcpy(&dp[ofs], pb, len);
|
memcpy(&dp[ofs], pb, len);
|
||||||
|
}
|
||||||
pb += len;
|
pb += len;
|
||||||
|
pb_size -= 1 + len;
|
||||||
ofs += len;
|
ofs += len;
|
||||||
} else {
|
} else {
|
||||||
/* interframe pixel copy */
|
/* interframe pixel copy */
|
||||||
if (ofs + len + 1 > frame_width)
|
if (ofs + len + 1 > frame_width || !s->prev_frame.data[0])
|
||||||
return;
|
return;
|
||||||
memcpy(&dp[ofs], &pp[ofs], len + 1);
|
memcpy(&dp[ofs], &pp[ofs], len + 1);
|
||||||
ofs += len + 1;
|
ofs += len + 1;
|
||||||
|
@@ -695,6 +695,7 @@ av_cold void vp56_init(AVCodecContext *avctx, int flip, int has_alpha)
|
|||||||
av_cold int vp56_free(AVCodecContext *avctx)
|
av_cold int vp56_free(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
VP56Context *s = avctx->priv_data;
|
VP56Context *s = avctx->priv_data;
|
||||||
|
int pt;
|
||||||
|
|
||||||
av_free(s->above_blocks);
|
av_free(s->above_blocks);
|
||||||
av_free(s->macroblocks);
|
av_free(s->macroblocks);
|
||||||
@@ -705,5 +706,15 @@ av_cold int vp56_free(AVCodecContext *avctx)
|
|||||||
avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN2]);
|
avctx->release_buffer(avctx, s->framep[VP56_FRAME_GOLDEN2]);
|
||||||
if (s->framep[VP56_FRAME_PREVIOUS]->data[0])
|
if (s->framep[VP56_FRAME_PREVIOUS]->data[0])
|
||||||
avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]);
|
avctx->release_buffer(avctx, s->framep[VP56_FRAME_PREVIOUS]);
|
||||||
|
|
||||||
|
for (pt=0; pt < 2; pt++) {
|
||||||
|
int ct, cg;
|
||||||
|
free_vlc(&s->dccv_vlc[pt]);
|
||||||
|
free_vlc(&s->runv_vlc[pt]);
|
||||||
|
for (ct=0; ct<3; ct++)
|
||||||
|
for (cg = 0; cg < 6; cg++)
|
||||||
|
free_vlc(&s->ract_vlc[pt][ct][cg]);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -136,8 +136,11 @@ static int vp6_parse_header(VP56Context *s, const uint8_t *buf, int buf_size,
|
|||||||
if (coeff_offset) {
|
if (coeff_offset) {
|
||||||
buf += coeff_offset;
|
buf += coeff_offset;
|
||||||
buf_size -= coeff_offset;
|
buf_size -= coeff_offset;
|
||||||
if (buf_size < 0)
|
if (buf_size < 0) {
|
||||||
|
if (s->framep[VP56_FRAME_CURRENT]->key_frame)
|
||||||
|
avcodec_set_dimensions(s->avctx, 0, 0);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
if (s->use_huffman) {
|
if (s->use_huffman) {
|
||||||
s->parse_coeff = vp6_parse_coeff_huffman;
|
s->parse_coeff = vp6_parse_coeff_huffman;
|
||||||
init_get_bits(&s->gb, buf, buf_size<<3);
|
init_get_bits(&s->gb, buf, buf_size<<3);
|
||||||
@@ -212,7 +215,7 @@ static int vp6_huff_cmp(const void *va, const void *vb)
|
|||||||
return (a->count - b->count)*16 + (b->sym - a->sym);
|
return (a->count - b->count)*16 + (b->sym - a->sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[],
|
static int vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[],
|
||||||
const uint8_t *map, unsigned size, VLC *vlc)
|
const uint8_t *map, unsigned size, VLC *vlc)
|
||||||
{
|
{
|
||||||
Node nodes[2*size], *tmp = &nodes[size];
|
Node nodes[2*size], *tmp = &nodes[size];
|
||||||
@@ -227,8 +230,9 @@ static void vp6_build_huff_tree(VP56Context *s, uint8_t coeff_model[],
|
|||||||
nodes[map[2*i+1]].count = b + !b;
|
nodes[map[2*i+1]].count = b + !b;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* then build the huffman tree accodring to probabilities */
|
free_vlc(vlc);
|
||||||
ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp,
|
/* then build the huffman tree according to probabilities */
|
||||||
|
return ff_huff_build_tree(s->avctx, vlc, size, nodes, vp6_huff_cmp,
|
||||||
FF_HUFFMAN_FLAG_HNODE_FIRST);
|
FF_HUFFMAN_FLAG_HNODE_FIRST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +369,7 @@ static void vp6_parse_coeff_huffman(VP56Context *s)
|
|||||||
if (b > 3) pt = 1;
|
if (b > 3) pt = 1;
|
||||||
vlc_coeff = &s->dccv_vlc[pt];
|
vlc_coeff = &s->dccv_vlc[pt];
|
||||||
|
|
||||||
for (coeff_idx=0; coeff_idx<64; ) {
|
for (coeff_idx = 0;;) {
|
||||||
int run = 1;
|
int run = 1;
|
||||||
if (coeff_idx<2 && s->nb_null[coeff_idx][pt]) {
|
if (coeff_idx<2 && s->nb_null[coeff_idx][pt]) {
|
||||||
s->nb_null[coeff_idx][pt]--;
|
s->nb_null[coeff_idx][pt]--;
|
||||||
@@ -400,6 +404,8 @@ static void vp6_parse_coeff_huffman(VP56Context *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
coeff_idx+=run;
|
coeff_idx+=run;
|
||||||
|
if (coeff_idx >= 64)
|
||||||
|
break;
|
||||||
cg = FFMIN(vp6_coeff_groups[coeff_idx], 3);
|
cg = FFMIN(vp6_coeff_groups[coeff_idx], 3);
|
||||||
vlc_coeff = &s->ract_vlc[pt][ct][cg];
|
vlc_coeff = &s->ract_vlc[pt][ct][cg];
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user