|
|
|
@ -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"), |
|
|
|
|