| @@ -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; | |||
| @@ -65,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; | |||
| } | |||
| @@ -199,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) { | |||
| @@ -217,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) { | |||
| @@ -239,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]); | |||
| } | |||
| } | |||
| @@ -320,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; | |||
| @@ -365,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; | |||
| @@ -384,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; | |||
| } | |||
| @@ -405,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; | |||
| @@ -413,18 +431,6 @@ 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"), | |||