diff options
Diffstat (limited to 'libavcodec/xxan.c')
-rw-r--r-- | libavcodec/xxan.c | 83 |
1 files changed, 49 insertions, 34 deletions
diff --git a/libavcodec/xxan.c b/libavcodec/xxan.c index 7446305..56d5f49 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; @@ -61,7 +63,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); } @@ -199,39 +207,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; @@ -239,16 +253,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]); } } @@ -270,7 +284,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; } @@ -315,17 +329,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; @@ -365,12 +382,12 @@ static int xan_decode_frame_type1(AVCodecContext *avctx) } 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; @@ -384,10 +401,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); @@ -405,7 +420,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; @@ -417,7 +432,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); |