X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fxxan.c;h=d77a50fd3f0a123dfc8409a6f9179b624a4fc4a8;hb=c697c590fbf296b1679b80c8f4071e4c8a6c884b;hp=47ab54a7f90ed56cb6e2ac410913dd094f339e62;hpb=759001c534287a96dc96d1e274665feb7059145d;p=ffmpeg diff --git a/libavcodec/xxan.c b/libavcodec/xxan.c index 47ab54a7f90..d77a50fd3f0 100644 --- a/libavcodec/xxan.c +++ b/libavcodec/xxan.c @@ -30,7 +30,7 @@ typedef struct XanContext { AVCodecContext *avctx; - AVFrame pic; + AVFrame *pic; uint8_t *y_buffer; uint8_t *scratch_buffer; @@ -38,6 +38,18 @@ typedef struct XanContext { GetByteContext gb; } XanContext; +static av_cold int xan_decode_end(AVCodecContext *avctx) +{ + XanContext *s = avctx->priv_data; + + av_frame_free(&s->pic); + + av_freep(&s->y_buffer); + av_freep(&s->scratch_buffer); + + return 0; +} + static av_cold int xan_decode_init(AVCodecContext *avctx) { XanContext *s = avctx->priv_data; @@ -50,6 +62,10 @@ static av_cold int xan_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height); return AVERROR(EINVAL); } + if (avctx->width & 1) { + av_log(avctx, AV_LOG_ERROR, "Invalid frame width: %d.\n", avctx->width); + return AVERROR(EINVAL); + } s->buffer_size = avctx->width * avctx->height; s->y_buffer = av_malloc(s->buffer_size); @@ -61,6 +77,12 @@ static av_cold int xan_decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); } + s->pic = av_frame_alloc(); + if (!s->pic) { + xan_decode_end(avctx); + return AVERROR(ENOMEM); + } + return 0; } @@ -195,8 +217,8 @@ 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) { @@ -213,16 +235,16 @@ static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off) 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) { @@ -235,16 +257,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]); } } @@ -308,7 +330,7 @@ static int xan_decode_frame_type0(AVCodecContext *avctx) int dec_size; bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET); - dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size); + dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2); if (dec_size < 0) dec_size = 0; for (i = 0; i < dec_size; i++) @@ -316,12 +338,12 @@ static int xan_decode_frame_type0(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; @@ -361,12 +383,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; @@ -380,7 +402,7 @@ static int xan_decode_frame(AVCodecContext *avctx, int ftype; int ret; - if ((ret = ff_reget_buffer(avctx, &s->pic))) { + if ((ret = ff_reget_buffer(avctx, s->pic))) { av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); return ret; } @@ -401,7 +423,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; @@ -409,20 +431,9 @@ static int xan_decode_frame(AVCodecContext *avctx, return avpkt->size; } -static av_cold int xan_decode_end(AVCodecContext *avctx) -{ - XanContext *s = avctx->priv_data; - - av_frame_unref(&s->pic); - - av_freep(&s->y_buffer); - av_freep(&s->scratch_buffer); - - return 0; -} - AVCodec ff_xan_wc4_decoder = { .name = "xan_wc4", + .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), .type = AVMEDIA_TYPE_VIDEO, .id = AV_CODEC_ID_XAN_WC4, .priv_data_size = sizeof(XanContext), @@ -430,5 +441,4 @@ AVCodec ff_xan_wc4_decoder = { .close = xan_decode_end, .decode = xan_decode_frame, .capabilities = CODEC_CAP_DR1, - .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), };