summaryrefslogtreecommitdiff
path: root/libavcodec/xxan.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/xxan.c')
-rw-r--r--libavcodec/xxan.c92
1 files changed, 55 insertions, 37 deletions
diff --git a/libavcodec/xxan.c b/libavcodec/xxan.c
index 2bc9ff697b..cb913da53a 100644
--- a/libavcodec/xxan.c
+++ b/libavcodec/xxan.c
@@ -3,20 +3,20 @@
* Copyright (C) 2011 Konstantin Shishkov
* based on work by Mike Melanson
*
- * 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.
*
- * Libav is distributed in the hope that it will be useful,
+ * 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -30,7 +30,7 @@
typedef struct XanContext {
AVCodecContext *avctx;
- AVFrame pic;
+ AVFrame *pic;
uint8_t *y_buffer;
uint8_t *scratch_buffer;
@@ -38,6 +38,8 @@ typedef struct XanContext {
GetByteContext gb;
} XanContext;
+static av_cold int xan_decode_end(AVCodecContext *avctx);
+
static av_cold int xan_decode_init(AVCodecContext *avctx)
{
XanContext *s = avctx->priv_data;
@@ -57,7 +59,13 @@ static av_cold int xan_decode_init(AVCodecContext *avctx)
return AVERROR(ENOMEM);
s->scratch_buffer = av_malloc(s->buffer_size + 130);
if (!s->scratch_buffer) {
- av_freep(&s->y_buffer);
+ xan_decode_end(avctx);
+ return AVERROR(ENOMEM);
+ }
+
+ s->pic = av_frame_alloc();
+ if (!s->pic) {
+ xan_decode_end(avctx);
return AVERROR(ENOMEM);
}
@@ -195,39 +203,45 @@ static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
return dec_size;
}
- U = s->pic.data[1];
- V = s->pic.data[2];
+ U = s->pic->data[1];
+ V = s->pic->data[2];
src = s->scratch_buffer;
src_end = src + dec_size;
if (mode) {
for (j = 0; j < avctx->height >> 1; j++) {
for (i = 0; i < avctx->width >> 1; i++) {
+ if (src_end - src < 1)
+ return 0;
val = *src++;
- if (val && val < table_size) {
+ if (val) {
+ if (val >= table_size)
+ return AVERROR_INVALIDDATA;
val = AV_RL16(table + (val << 1));
uval = (val >> 3) & 0xF8;
vval = (val >> 8) & 0xF8;
U[i] = uval | (uval >> 5);
V[i] = vval | (vval >> 5);
}
- if (src == src_end)
- return 0;
}
- U += s->pic.linesize[1];
- V += s->pic.linesize[2];
+ U += s->pic->linesize[1];
+ V += s->pic->linesize[2];
}
if (avctx->height & 1) {
- memcpy(U, U - s->pic.linesize[1], avctx->width >> 1);
- memcpy(V, V - s->pic.linesize[2], avctx->width >> 1);
+ memcpy(U, U - s->pic->linesize[1], avctx->width >> 1);
+ memcpy(V, V - s->pic->linesize[2], avctx->width >> 1);
}
} else {
- uint8_t *U2 = U + s->pic.linesize[1];
- uint8_t *V2 = V + s->pic.linesize[2];
+ uint8_t *U2 = U + s->pic->linesize[1];
+ uint8_t *V2 = V + s->pic->linesize[2];
for (j = 0; j < avctx->height >> 2; j++) {
for (i = 0; i < avctx->width >> 1; i += 2) {
+ if (src_end - src < 1)
+ return 0;
val = *src++;
- if (val && val < table_size) {
+ if (val) {
+ if (val >= table_size)
+ return AVERROR_INVALIDDATA;
val = AV_RL16(table + (val << 1));
uval = (val >> 3) & 0xF8;
vval = (val >> 8) & 0xF8;
@@ -235,16 +249,16 @@ static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
}
}
- U += s->pic.linesize[1] * 2;
- V += s->pic.linesize[2] * 2;
- U2 += s->pic.linesize[1] * 2;
- V2 += s->pic.linesize[2] * 2;
+ U += s->pic->linesize[1] * 2;
+ V += s->pic->linesize[2] * 2;
+ U2 += s->pic->linesize[1] * 2;
+ V2 += s->pic->linesize[2] * 2;
}
if (avctx->height & 3) {
int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2;
- memcpy(U, U - lines * s->pic.linesize[1], lines * s->pic.linesize[1]);
- memcpy(V, V - lines * s->pic.linesize[2], lines * s->pic.linesize[2]);
+ memcpy(U, U - lines * s->pic->linesize[1], lines * s->pic->linesize[1]);
+ memcpy(V, V - lines * s->pic->linesize[2], lines * s->pic->linesize[2]);
}
}
@@ -266,7 +280,7 @@ static int xan_decode_frame_type0(AVCodecContext *avctx)
if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0)
return ret;
- if (corr_off >= (s->gb.buffer_end - s->gb.buffer_start)) {
+ if (corr_off >= bytestream2_size(&s->gb)) {
av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
corr_off = 0;
}
@@ -286,7 +300,8 @@ static int xan_decode_frame_type0(AVCodecContext *avctx)
ybuf[j+1] = cur << 1;
last = cur;
}
- ybuf[j] = last << 1;
+ if(j < avctx->width)
+ ybuf[j] = last << 1;
prev_buf = ybuf;
ybuf += avctx->width;
@@ -299,7 +314,8 @@ static int xan_decode_frame_type0(AVCodecContext *avctx)
ybuf[j+1] = cur << 1;
last = cur;
}
- ybuf[j] = last << 1;
+ if(j < avctx->width)
+ ybuf[j] = last << 1;
prev_buf = ybuf;
ybuf += avctx->width;
}
@@ -311,17 +327,20 @@ static int xan_decode_frame_type0(AVCodecContext *avctx)
dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2);
if (dec_size < 0)
dec_size = 0;
+ else
+ dec_size = FFMIN(dec_size, s->buffer_size/2 - 1);
+
for (i = 0; i < dec_size; i++)
s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
}
src = s->y_buffer;
- ybuf = s->pic.data[0];
+ ybuf = s->pic->data[0];
for (j = 0; j < avctx->height; j++) {
for (i = 0; i < avctx->width; i++)
ybuf[i] = (src[i] << 2) | (src[i] >> 3);
src += avctx->width;
- ybuf += s->pic.linesize[0];
+ ybuf += s->pic->linesize[0];
}
return 0;
@@ -356,17 +375,18 @@ static int xan_decode_frame_type1(AVCodecContext *avctx)
ybuf[j+1] = cur;
last = cur;
}
- ybuf[j] = last;
+ if(j < avctx->width)
+ ybuf[j] = last;
ybuf += avctx->width;
}
src = s->y_buffer;
- ybuf = s->pic.data[0];
+ ybuf = s->pic->data[0];
for (j = 0; j < avctx->height; j++) {
for (i = 0; i < avctx->width; i++)
ybuf[i] = (src[i] << 2) | (src[i] >> 3);
src += avctx->width;
- ybuf += s->pic.linesize[0];
+ ybuf += s->pic->linesize[0];
}
return 0;
@@ -380,10 +400,8 @@ static int xan_decode_frame(AVCodecContext *avctx,
int ftype;
int ret;
- if ((ret = ff_reget_buffer(avctx, &s->pic))) {
- av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
+ if ((ret = ff_reget_buffer(avctx, s->pic)) < 0)
return ret;
- }
bytestream2_init(&s->gb, avpkt->data, avpkt->size);
ftype = bytestream2_get_le32(&s->gb);
@@ -401,7 +419,7 @@ static int xan_decode_frame(AVCodecContext *avctx,
if (ret)
return ret;
- if ((ret = av_frame_ref(data, &s->pic)) < 0)
+ if ((ret = av_frame_ref(data, s->pic)) < 0)
return ret;
*got_frame = 1;
@@ -413,7 +431,7 @@ static av_cold int xan_decode_end(AVCodecContext *avctx)
{
XanContext *s = avctx->priv_data;
- av_frame_unref(&s->pic);
+ av_frame_free(&s->pic);
av_freep(&s->y_buffer);
av_freep(&s->scratch_buffer);