2 * Wing Commander/Xan Video Decoder
3 * Copyright (C) 2011 Konstantin Shishkov
4 * based on work by Mike Melanson
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/mem.h"
26 #include "bytestream.h"
27 #define BITSTREAM_READER_LE
31 typedef struct XanContext {
32 AVCodecContext *avctx;
36 uint8_t *scratch_buffer;
41 static av_cold int xan_decode_end(AVCodecContext *avctx);
43 static av_cold int xan_decode_init(AVCodecContext *avctx)
45 XanContext *s = avctx->priv_data;
49 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
51 if (avctx->height < 8) {
52 av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height);
53 return AVERROR(EINVAL);
55 if (avctx->width & 1) {
56 av_log(avctx, AV_LOG_ERROR, "Invalid frame width: %d.\n", avctx->width);
57 return AVERROR(EINVAL);
60 s->buffer_size = avctx->width * avctx->height;
61 s->y_buffer = av_malloc(s->buffer_size);
63 return AVERROR(ENOMEM);
64 s->scratch_buffer = av_malloc(s->buffer_size + 130);
65 if (!s->scratch_buffer) {
66 xan_decode_end(avctx);
67 return AVERROR(ENOMEM);
70 s->pic = av_frame_alloc();
72 xan_decode_end(avctx);
73 return AVERROR(ENOMEM);
79 static int xan_unpack_luma(XanContext *s,
80 uint8_t *dst, const int dst_size)
85 const uint8_t *dst_end = dst + dst_size;
86 GetByteContext tree = s->gb;
87 int start_off = bytestream2_tell(&tree);
89 tree_size = bytestream2_get_byte(&s->gb);
90 eof = bytestream2_get_byte(&s->gb);
91 tree_root = eof + tree_size;
92 bytestream2_skip(&s->gb, tree_size * 2);
95 bits = bytestream2_get_byte(&s->gb);
98 int bit = !!(bits & mask);
100 bytestream2_seek(&tree, start_off + node*2 + bit - eof * 2, SEEK_SET);
101 node = bytestream2_get_byte(&tree);
111 if (bytestream2_get_bytes_left(&s->gb) <= 0)
113 bits = bytestream2_get_byteu(&s->gb);
117 return dst != dst_end ? AVERROR_INVALIDDATA : 0;
120 /* almost the same as in xan_wc3 decoder */
121 static int xan_unpack(XanContext *s,
122 uint8_t *dest, const int dest_len)
126 uint8_t *orig_dest = dest;
127 const uint8_t *dest_end = dest + dest_len;
129 while (dest < dest_end) {
130 if (bytestream2_get_bytes_left(&s->gb) <= 0)
131 return AVERROR_INVALIDDATA;
133 opcode = bytestream2_get_byteu(&s->gb);
137 if ((opcode & 0x80) == 0) {
139 back = ((opcode & 0x60) << 3) + bytestream2_get_byte(&s->gb) + 1;
140 size2 = ((opcode & 0x1c) >> 2) + 3;
141 } else if ((opcode & 0x40) == 0) {
142 size = bytestream2_peek_byte(&s->gb) >> 6;
143 back = (bytestream2_get_be16(&s->gb) & 0x3fff) + 1;
144 size2 = (opcode & 0x3f) + 4;
147 back = ((opcode & 0x10) << 12) + bytestream2_get_be16(&s->gb) + 1;
148 size2 = ((opcode & 0x0c) << 6) + bytestream2_get_byte(&s->gb) + 5;
149 if (size + size2 > dest_end - dest)
152 if (dest + size + size2 > dest_end ||
153 dest - orig_dest + size < back)
154 return AVERROR_INVALIDDATA;
155 bytestream2_get_buffer(&s->gb, dest, size);
157 av_memcpy_backptr(dest, back, size2);
160 int finish = opcode >= 0xfc;
162 size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
163 if (dest_end - dest < size)
164 return AVERROR_INVALIDDATA;
165 bytestream2_get_buffer(&s->gb, dest, size);
171 return dest - orig_dest;
174 static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
176 XanContext *s = avctx->priv_data;
180 const uint8_t *src, *src_end;
181 const uint8_t *table;
182 int mode, offset, dec_size, table_size;
186 if (chroma_off + 4 >= bytestream2_get_bytes_left(&s->gb)) {
187 av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n");
188 return AVERROR_INVALIDDATA;
190 bytestream2_seek(&s->gb, chroma_off + 4, SEEK_SET);
191 mode = bytestream2_get_le16(&s->gb);
192 table = s->gb.buffer;
193 table_size = bytestream2_get_le16(&s->gb);
194 offset = table_size * 2;
197 if (offset >= bytestream2_get_bytes_left(&s->gb)) {
198 av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n");
199 return AVERROR_INVALIDDATA;
202 bytestream2_skip(&s->gb, offset);
203 memset(s->scratch_buffer, 0, s->buffer_size);
204 dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size);
206 av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n");
212 src = s->scratch_buffer;
213 src_end = src + dec_size;
215 for (j = 0; j < avctx->height >> 1; j++) {
216 for (i = 0; i < avctx->width >> 1; i++) {
217 if (src_end - src < 1)
221 if (val >= table_size)
222 return AVERROR_INVALIDDATA;
223 val = AV_RL16(table + (val << 1));
224 uval = (val >> 3) & 0xF8;
225 vval = (val >> 8) & 0xF8;
226 U[i] = uval | (uval >> 5);
227 V[i] = vval | (vval >> 5);
230 U += s->pic->linesize[1];
231 V += s->pic->linesize[2];
233 if (avctx->height & 1) {
234 memcpy(U, U - s->pic->linesize[1], avctx->width >> 1);
235 memcpy(V, V - s->pic->linesize[2], avctx->width >> 1);
238 uint8_t *U2 = U + s->pic->linesize[1];
239 uint8_t *V2 = V + s->pic->linesize[2];
241 for (j = 0; j < avctx->height >> 2; j++) {
242 for (i = 0; i < avctx->width >> 1; i += 2) {
243 if (src_end - src < 1)
247 if (val >= table_size)
248 return AVERROR_INVALIDDATA;
249 val = AV_RL16(table + (val << 1));
250 uval = (val >> 3) & 0xF8;
251 vval = (val >> 8) & 0xF8;
252 U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5);
253 V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
256 U += s->pic->linesize[1] * 2;
257 V += s->pic->linesize[2] * 2;
258 U2 += s->pic->linesize[1] * 2;
259 V2 += s->pic->linesize[2] * 2;
261 if (avctx->height & 3) {
262 int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2;
264 memcpy(U, U - lines * s->pic->linesize[1], lines * s->pic->linesize[1]);
265 memcpy(V, V - lines * s->pic->linesize[2], lines * s->pic->linesize[2]);
272 static int xan_decode_frame_type0(AVCodecContext *avctx)
274 XanContext *s = avctx->priv_data;
275 uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer;
276 unsigned chroma_off, corr_off;
281 chroma_off = bytestream2_get_le32(&s->gb);
282 corr_off = bytestream2_get_le32(&s->gb);
284 if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0)
287 if (corr_off >= bytestream2_size(&s->gb)) {
288 av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
291 bytestream2_seek(&s->gb, 12, SEEK_SET);
292 ret = xan_unpack_luma(s, src, s->buffer_size >> 1);
294 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
301 for (j = 1; j < avctx->width - 1; j += 2) {
302 cur = (last + *src++) & 0x1F;
303 ybuf[j] = last + cur;
304 ybuf[j+1] = cur << 1;
309 ybuf += avctx->width;
311 for (i = 1; i < avctx->height; i++) {
312 last = ((prev_buf[0] >> 1) + *src++) & 0x1F;
314 for (j = 1; j < avctx->width - 1; j += 2) {
315 cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F;
316 ybuf[j] = last + cur;
317 ybuf[j+1] = cur << 1;
322 ybuf += avctx->width;
328 bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET);
329 dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2);
333 dec_size = FFMIN(dec_size, s->buffer_size/2 - 1);
335 for (i = 0; i < dec_size; i++)
336 s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
340 ybuf = s->pic->data[0];
341 for (j = 0; j < avctx->height; j++) {
342 for (i = 0; i < avctx->width; i++)
343 ybuf[i] = (src[i] << 2) | (src[i] >> 3);
345 ybuf += s->pic->linesize[0];
351 static int xan_decode_frame_type1(AVCodecContext *avctx)
353 XanContext *s = avctx->priv_data;
354 uint8_t *ybuf, *src = s->scratch_buffer;
359 if ((ret = xan_decode_chroma(avctx, bytestream2_get_le32(&s->gb))) != 0)
362 bytestream2_seek(&s->gb, 16, SEEK_SET);
363 ret = xan_unpack_luma(s, src,
364 s->buffer_size >> 1);
366 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
371 for (i = 0; i < avctx->height; i++) {
372 last = (ybuf[0] + (*src++ << 1)) & 0x3F;
374 for (j = 1; j < avctx->width - 1; j += 2) {
375 cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F;
376 ybuf[j] = (last + cur) >> 1;
381 ybuf += avctx->width;
385 ybuf = s->pic->data[0];
386 for (j = 0; j < avctx->height; j++) {
387 for (i = 0; i < avctx->width; i++)
388 ybuf[i] = (src[i] << 2) | (src[i] >> 3);
390 ybuf += s->pic->linesize[0];
396 static int xan_decode_frame(AVCodecContext *avctx,
397 void *data, int *got_frame,
400 XanContext *s = avctx->priv_data;
404 if ((ret = ff_reget_buffer(avctx, s->pic)) < 0)
407 bytestream2_init(&s->gb, avpkt->data, avpkt->size);
408 ftype = bytestream2_get_le32(&s->gb);
411 ret = xan_decode_frame_type0(avctx);
414 ret = xan_decode_frame_type1(avctx);
417 av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype);
418 return AVERROR_INVALIDDATA;
423 if ((ret = av_frame_ref(data, s->pic)) < 0)
431 static av_cold int xan_decode_end(AVCodecContext *avctx)
433 XanContext *s = avctx->priv_data;
435 av_frame_free(&s->pic);
437 av_freep(&s->y_buffer);
438 av_freep(&s->scratch_buffer);
443 AVCodec ff_xan_wc4_decoder = {
445 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
446 .type = AVMEDIA_TYPE_VIDEO,
447 .id = AV_CODEC_ID_XAN_WC4,
448 .priv_data_size = sizeof(XanContext),
449 .init = xan_decode_init,
450 .close = xan_decode_end,
451 .decode = xan_decode_frame,
452 .capabilities = CODEC_CAP_DR1,