xxan: use the AVFrame API properly.

This commit is contained in:
Anton Khirnov 2013-11-09 10:14:46 +01:00
parent 6886a85f5c
commit f3cd23fbc8

View File

@ -30,7 +30,7 @@
typedef struct XanContext { typedef struct XanContext {
AVCodecContext *avctx; AVCodecContext *avctx;
AVFrame pic; AVFrame *pic;
uint8_t *y_buffer; uint8_t *y_buffer;
uint8_t *scratch_buffer; uint8_t *scratch_buffer;
@ -38,6 +38,18 @@ typedef struct XanContext {
GetByteContext gb; GetByteContext gb;
} XanContext; } 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) static av_cold int xan_decode_init(AVCodecContext *avctx)
{ {
XanContext *s = avctx->priv_data; XanContext *s = avctx->priv_data;
@ -65,6 +77,12 @@ static av_cold int xan_decode_init(AVCodecContext *avctx)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
} }
s->pic = av_frame_alloc();
if (!s->pic) {
xan_decode_end(avctx);
return AVERROR(ENOMEM);
}
return 0; return 0;
} }
@ -199,8 +217,8 @@ static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
return dec_size; return dec_size;
} }
U = s->pic.data[1]; U = s->pic->data[1];
V = s->pic.data[2]; V = s->pic->data[2];
src = s->scratch_buffer; src = s->scratch_buffer;
src_end = src + dec_size; src_end = src + dec_size;
if (mode) { if (mode) {
@ -217,16 +235,16 @@ static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
if (src == src_end) if (src == src_end)
return 0; return 0;
} }
U += s->pic.linesize[1]; U += s->pic->linesize[1];
V += s->pic.linesize[2]; V += s->pic->linesize[2];
} }
if (avctx->height & 1) { if (avctx->height & 1) {
memcpy(U, U - s->pic.linesize[1], avctx->width >> 1); memcpy(U, U - s->pic->linesize[1], avctx->width >> 1);
memcpy(V, V - s->pic.linesize[2], avctx->width >> 1); memcpy(V, V - s->pic->linesize[2], avctx->width >> 1);
} }
} else { } else {
uint8_t *U2 = U + s->pic.linesize[1]; uint8_t *U2 = U + s->pic->linesize[1];
uint8_t *V2 = V + s->pic.linesize[2]; uint8_t *V2 = V + s->pic->linesize[2];
for (j = 0; j < avctx->height >> 2; j++) { for (j = 0; j < avctx->height >> 2; j++) {
for (i = 0; i < avctx->width >> 1; i += 2) { 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); V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
} }
} }
U += s->pic.linesize[1] * 2; U += s->pic->linesize[1] * 2;
V += s->pic.linesize[2] * 2; V += s->pic->linesize[2] * 2;
U2 += s->pic.linesize[1] * 2; U2 += s->pic->linesize[1] * 2;
V2 += s->pic.linesize[2] * 2; V2 += s->pic->linesize[2] * 2;
} }
if (avctx->height & 3) { if (avctx->height & 3) {
int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2; int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2;
memcpy(U, U - lines * s->pic.linesize[1], lines * s->pic.linesize[1]); 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(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; src = s->y_buffer;
ybuf = s->pic.data[0]; ybuf = s->pic->data[0];
for (j = 0; j < avctx->height; j++) { for (j = 0; j < avctx->height; j++) {
for (i = 0; i < avctx->width; i++) for (i = 0; i < avctx->width; i++)
ybuf[i] = (src[i] << 2) | (src[i] >> 3); ybuf[i] = (src[i] << 2) | (src[i] >> 3);
src += avctx->width; src += avctx->width;
ybuf += s->pic.linesize[0]; ybuf += s->pic->linesize[0];
} }
return 0; return 0;
@ -365,12 +383,12 @@ static int xan_decode_frame_type1(AVCodecContext *avctx)
} }
src = s->y_buffer; src = s->y_buffer;
ybuf = s->pic.data[0]; ybuf = s->pic->data[0];
for (j = 0; j < avctx->height; j++) { for (j = 0; j < avctx->height; j++) {
for (i = 0; i < avctx->width; i++) for (i = 0; i < avctx->width; i++)
ybuf[i] = (src[i] << 2) | (src[i] >> 3); ybuf[i] = (src[i] << 2) | (src[i] >> 3);
src += avctx->width; src += avctx->width;
ybuf += s->pic.linesize[0]; ybuf += s->pic->linesize[0];
} }
return 0; return 0;
@ -384,7 +402,7 @@ static int xan_decode_frame(AVCodecContext *avctx,
int ftype; int ftype;
int ret; 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"); av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
return ret; return ret;
} }
@ -405,7 +423,7 @@ static int xan_decode_frame(AVCodecContext *avctx,
if (ret) if (ret)
return ret; return ret;
if ((ret = av_frame_ref(data, &s->pic)) < 0) if ((ret = av_frame_ref(data, s->pic)) < 0)
return ret; return ret;
*got_frame = 1; *got_frame = 1;
@ -413,18 +431,6 @@ static int xan_decode_frame(AVCodecContext *avctx,
return avpkt->size; 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 = { AVCodec ff_xan_wc4_decoder = {
.name = "xan_wc4", .name = "xan_wc4",
.long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),