History

Xan4 decoder

Kostya Shishkov committed 15 years ago

Commit abb5f2b1 parent 14d735b6 files · +435 −2Browse files

Unified · Split

6 files
  1. Changelog +1 −0
  2. doc/general.texi +2 −0
  3. libavcodec/Makefile +1 −1
  4. libavcodec/allcodecs.c +1 −0
  5. libavcodec/avcodec.h +1 −1
  6. libavcodec/xxan.c +429 −0
Changelog+1−0
@@ -74,6 +74,7 @@ version <next>: · 73 unmodified lines
7474 - Lagarith decoder
7575 - ffmpeg -copytb option added
7676 - IVF muxer added
77+- Wing Commander IV movies decoder added
7778
7879
7980 version 0.6:
doc/general.texi+2−0
@@ -511,6 +511,8 @@ following image formats are supported: · 510 unmodified lines
511511 @tab not completely working
512512 @item Wing Commander III / Xan @tab @tab X
513513 @tab Used in Wing Commander III .MVE files.
514+@item Wing Commander IV / Xan @tab @tab X
515+ @tab Used in Wing Commander IV.
514516 @item Winnov WNV1 @tab @tab X
515517 @item WMV7 @tab X @tab X
516518 @item YAMAHA SMAF @tab X @tab X
libavcodec/Makefile+1−1
@@ -415,7 +415,7 @@ OBJS-$(CONFIG_WNV1_DECODER) += wnv1.o · 414 unmodified lines
415415 OBJS-$(CONFIG_WS_SND1_DECODER) += ws-snd1.o
416416 OBJS-$(CONFIG_XAN_DPCM_DECODER) += dpcm.o
417417 OBJS-$(CONFIG_XAN_WC3_DECODER) += xan.o
418−OBJS-$(CONFIG_XAN_WC4_DECODER) += xan.o
418+OBJS-$(CONFIG_XAN_WC4_DECODER) += xxan.o
419419 OBJS-$(CONFIG_XL_DECODER) += xl.o
420420 OBJS-$(CONFIG_XSUB_DECODER) += xsubdec.o
421421 OBJS-$(CONFIG_XSUB_ENCODER) += xsubenc.o
libavcodec/allcodecs.c+1−0
@@ -214,6 +214,7 @@ void avcodec_register_all(void) · 213 unmodified lines
214214 REGISTER_DECODER (WMV3_VDPAU, wmv3_vdpau);
215215 REGISTER_DECODER (WNV1, wnv1);
216216 REGISTER_DECODER (XAN_WC3, xan_wc3);
217+ REGISTER_DECODER (XAN_WC4, xan_wc4);
217218 REGISTER_DECODER (XL, xl);
218219 REGISTER_DECODER (YOP, yop);
219220 REGISTER_ENCDEC (ZLIB, zlib);
libavcodec/avcodec.h+1−1
@@ -32,7 +32,7 @@ · 31 unmodified lines
3232 #include "libavutil/cpu.h"
3333
3434 #define LIBAVCODEC_VERSION_MAJOR 52
35−#define LIBAVCODEC_VERSION_MINOR 109
35+#define LIBAVCODEC_VERSION_MINOR 110
3636 #define LIBAVCODEC_VERSION_MICRO 0
3737
3838 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
libavcodec/xxan.c+429−0
@@ -0,0 +1,429 @@
1+/*
2+ * Wing Commander/Xan Video Decoder
3+ * Copyright (C) 2011 Konstantin Shishkov
4+ * based on work by Mike Melanson
5+ *
6+ * This file is part of FFmpeg.
7+ *
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.
12+ *
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.
17+ *
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
21+ */
22+
23+#include "avcodec.h"
24+#include "libavutil/intreadwrite.h"
25+#include "bytestream.h"
26+#define ALT_BITSTREAM_READER_LE
27+#include "get_bits.h"
28+// for av_memcpy_backptr
29+#include "libavutil/lzo.h"
30+
31+typedef struct XanContext {
32+ AVCodecContext *avctx;
33+ AVFrame pic;
34+
35+ uint8_t *y_buffer;
36+ uint8_t *scratch_buffer;
37+ int buffer_size;
38+} XanContext;
39+
40+static av_cold int xan_decode_init(AVCodecContext *avctx)
41+{
42+ XanContext *s = avctx->priv_data;
43+
44+ s->avctx = avctx;
45+
46+ avctx->pix_fmt = PIX_FMT_YUV420P;
47+
48+ s->buffer_size = avctx->width * avctx->height;
49+ s->y_buffer = av_malloc(s->buffer_size);
50+ if (!s->y_buffer)
51+ return AVERROR(ENOMEM);
52+ s->scratch_buffer = av_malloc(s->buffer_size + 130);
53+ if (!s->scratch_buffer) {
54+ av_freep(&s->y_buffer);
55+ return AVERROR(ENOMEM);
56+ }
57+
58+ return 0;
59+}
60+
61+static int xan_unpack_luma(const uint8_t *src, const int src_size,
62+ uint8_t *dst, const int dst_size)
63+{
64+ int tree_size, eof;
65+ const uint8_t *tree;
66+ int bits, mask;
67+ int tree_root, node;
68+ const uint8_t *dst_end = dst + dst_size;
69+ const uint8_t *src_end = src + src_size;
70+
71+ tree_size = *src++;
72+ eof = *src++;
73+ tree = src - eof * 2 - 2;
74+ tree_root = eof + tree_size;
75+ src += tree_size * 2;
76+
77+ node = tree_root;
78+ bits = *src++;
79+ mask = 0x80;
80+ for (;;) {
81+ int bit = !!(bits & mask);
82+ mask >>= 1;
83+ node = tree[node*2 + bit];
84+ if (node == eof)
85+ break;
86+ if (node < eof) {
87+ *dst++ = node;
88+ if (dst > dst_end)
89+ break;
90+ node = tree_root;
91+ }
92+ if (!mask) {
93+ bits = *src++;
94+ if (src > src_end)
95+ break;
96+ mask = 0x80;
97+ }
98+ }
99+ return dst != dst_end;
100+}
101+
102+/* almost the same as in xan_wc3 decoder */
103+static int xan_unpack(uint8_t *dest, const int dest_len,
104+ const uint8_t *src, const int src_len)
105+{
106+ uint8_t opcode;
107+ int size;
108+ uint8_t *orig_dest = dest;
109+ const uint8_t *src_end = src + src_len;
110+ const uint8_t *dest_end = dest + dest_len;
111+
112+ while (dest < dest_end) {
113+ opcode = *src++;
114+
115+ if (opcode < 0xe0) {
116+ int size2, back;
117+ if ((opcode & 0x80) == 0) {
118+ size = opcode & 3;
119+ back = ((opcode & 0x60) << 3) + *src++ + 1;
120+ size2 = ((opcode & 0x1c) >> 2) + 3;
121+ } else if ((opcode & 0x40) == 0) {
122+ size = *src >> 6;
123+ back = (bytestream_get_be16(&src) & 0x3fff) + 1;
124+ size2 = (opcode & 0x3f) + 4;
125+ } else {
126+ size = opcode & 3;
127+ back = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1;
128+ size2 = ((opcode & 0x0c) << 6) + *src++ + 5;
129+ if (size + size2 > dest_end - dest)
130+ break;
131+ }
132+ if (src + size > src_end || dest + size + size2 > dest_end)
133+ return -1;
134+ bytestream_get_buffer(&src, dest, size);
135+ dest += size;
136+ av_memcpy_backptr(dest, back, size2);
137+ dest += size2;
138+ } else {
139+ int finish = opcode >= 0xfc;
140+
141+ size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
142+ if (src + size > src_end || dest + size > dest_end)
143+ return -1;
144+ bytestream_get_buffer(&src, dest, size);
145+ dest += size;
146+ if (finish)
147+ break;
148+ }
149+ }
150+ return dest - orig_dest;
151+}
152+
153+static int xan_decode_chroma(AVCodecContext *avctx, AVPacket *avpkt)
154+{
155+ const uint8_t *buf = avpkt->data;
156+ XanContext *s = avctx->priv_data;
157+ uint8_t *U, *V;
158+ unsigned chroma_off;
159+ int val, uval, vval;
160+ int i, j;
161+ const uint8_t *src, *src_end;
162+ const uint8_t *table;
163+ int mode, offset, dec_size;
164+
165+ chroma_off = AV_RL32(buf + 4);
166+ if (!chroma_off)
167+ return 0;
168+ if (chroma_off + 10 >= avpkt->size) {
169+ av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n");
170+ return -1;
171+ }
172+ src = avpkt->data + 4 + chroma_off;
173+ table = src + 2;
174+ mode = bytestream_get_le16(&src);
175+ offset = bytestream_get_le16(&src) * 2;
176+
177+ if (src - avpkt->data >= avpkt->size - offset) {
178+ av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n");
179+ return -1;
180+ }
181+
182+ memset(s->scratch_buffer, 0, s->buffer_size);
183+ dec_size = xan_unpack(s->scratch_buffer, s->buffer_size, src + offset,
184+ avpkt->size - offset - (src - avpkt->data));
185+ if (dec_size < 0) {
186+ av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n");
187+ return -1;
188+ }
189+
190+ U = s->pic.data[1];
191+ V = s->pic.data[2];
192+ src = s->scratch_buffer;
193+ src_end = src + dec_size;
194+ if (mode) {
195+ for (j = 0; j < avctx->height >> 1; j++) {
196+ for (i = 0; i < avctx->width >> 1; i++) {
197+ val = *src++;
198+ if (val) {
199+ val = AV_RL16(table + (val << 1));
200+ uval = (val >> 3) & 0xF8;
201+ vval = (val >> 8) & 0xF8;
202+ U[i] = uval | (uval >> 5);
203+ V[i] = vval | (vval >> 5);
204+ }
205+ if (src == src_end)
206+ return 0;
207+ }
208+ U += s->pic.linesize[1];
209+ V += s->pic.linesize[2];
210+ }
211+ } else {
212+ uint8_t *U2 = U + s->pic.linesize[1];
213+ uint8_t *V2 = V + s->pic.linesize[2];
214+
215+ for (j = 0; j < avctx->height >> 2; j++) {
216+ for (i = 0; i < avctx->width >> 1; i += 2) {
217+ val = *src++;
218+ if (val) {
219+ val = AV_RL16(table + (val << 1));
220+ uval = (val >> 3) & 0xF8;
221+ vval = (val >> 8) & 0xF8;
222+ U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5);
223+ V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
224+ }
225+ }
226+ U += s->pic.linesize[1] * 2;
227+ V += s->pic.linesize[2] * 2;
228+ U2 += s->pic.linesize[1] * 2;
229+ V2 += s->pic.linesize[2] * 2;
230+ }
231+ }
232+
233+ return 0;
234+}
235+
236+static int xan_decode_frame_type0(AVCodecContext *avctx, AVPacket *avpkt)
237+{
238+ const uint8_t *buf = avpkt->data;
239+ XanContext *s = avctx->priv_data;
240+ uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer;
241+ unsigned chroma_off, corr_off;
242+ int cur, last, size;
243+ int i, j;
244+ int ret;
245+
246+ corr_off = AV_RL32(buf + 8);
247+ chroma_off = AV_RL32(buf + 4);
248+
249+ if ((ret = xan_decode_chroma(avctx, avpkt)) != 0)
250+ return ret;
251+
252+ size = avpkt->size - 4;
253+ if (corr_off >= avpkt->size) {
254+ av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
255+ corr_off = 0;
256+ }
257+ if (corr_off)
258+ size = corr_off;
259+ if (chroma_off)
260+ size = FFMIN(size, chroma_off);
261+ ret = xan_unpack_luma(buf + 12, size, src, s->buffer_size >> 1);
262+ if (ret) {
263+ av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
264+ return ret;
265+ }
266+
267+ ybuf = s->y_buffer;
268+ last = *src++;
269+ ybuf[0] = last << 1;
270+ for (j = 1; j < avctx->width - 1; j += 2) {
271+ cur = (last + *src++) & 0x1F;
272+ ybuf[j] = last + cur;
273+ ybuf[j+1] = cur << 1;
274+ last = cur;
275+ }
276+ ybuf[j] = last << 1;
277+ prev_buf = ybuf;
278+ ybuf += avctx->width;
279+
280+ for (i = 1; i < avctx->height; i++) {
281+ last = ((prev_buf[0] >> 1) + *src++) & 0x1F;
282+ ybuf[0] = last << 1;
283+ for (j = 1; j < avctx->width - 1; j += 2) {
284+ cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F;
285+ ybuf[j] = last + cur;
286+ ybuf[j+1] = cur << 1;
287+ last = cur;
288+ }
289+ ybuf[j] = last << 1;
290+ prev_buf = ybuf;
291+ ybuf += avctx->width;
292+ }
293+
294+ if (corr_off) {
295+ int corr_end, dec_size;
296+
297+ corr_end = avpkt->size;
298+ if (chroma_off > corr_off)
299+ corr_end = chroma_off;
300+ dec_size = xan_unpack(s->scratch_buffer, s->buffer_size,
301+ avpkt->data + 8 + corr_off,
302+ corr_end - corr_off);
303+ if (dec_size < 0)
304+ dec_size = 0;
305+ for (i = 0; i < dec_size; i++)
306+ s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
307+ }
308+
309+ src = s->y_buffer;
310+ ybuf = s->pic.data[0];
311+ for (j = 0; j < avctx->height; j++) {
312+ for (i = 0; i < avctx->width; i++)
313+ ybuf[i] = (src[i] << 2) | (src[i] >> 3);
314+ src += avctx->width;
315+ ybuf += s->pic.linesize[0];
316+ }
317+
318+ return 0;
319+}
320+
321+static int xan_decode_frame_type1(AVCodecContext *avctx, AVPacket *avpkt)
322+{
323+ const uint8_t *buf = avpkt->data;
324+ XanContext *s = avctx->priv_data;
325+ uint8_t *ybuf, *src = s->scratch_buffer;
326+ int cur, last;
327+ int i, j;
328+ int ret;
329+
330+ if ((ret = xan_decode_chroma(avctx, avpkt)) != 0)
331+ return ret;
332+
333+ ret = xan_unpack_luma(buf + 16, avpkt->size - 16, src,
334+ s->buffer_size >> 1);
335+ if (ret) {
336+ av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
337+ return ret;
338+ }
339+
340+ ybuf = s->y_buffer;
341+ for (i = 0; i < avctx->height; i++) {
342+ last = (ybuf[0] + (*src++ << 1)) & 0x3F;
343+ ybuf[0] = last;
344+ for (j = 1; j < avctx->width - 1; j += 2) {
345+ cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F;
346+ ybuf[j] = (last + cur) >> 1;
347+ ybuf[j+1] = cur;
348+ last = cur;
349+ }
350+ ybuf[j] = last;
351+ ybuf += avctx->width;
352+ }
353+
354+ src = s->y_buffer;
355+ ybuf = s->pic.data[0];
356+ for (j = 0; j < avctx->height; j++) {
357+ for (i = 0; i < avctx->width; i++)
358+ ybuf[i] = (src[i] << 2) | (src[i] >> 3);
359+ src += avctx->width;
360+ ybuf += s->pic.linesize[0];
361+ }
362+
363+ return 0;
364+}
365+
366+static int xan_decode_frame(AVCodecContext *avctx,
367+ void *data, int *data_size,
368+ AVPacket *avpkt)
369+{
370+ XanContext *s = avctx->priv_data;
371+ int ftype;
372+ int ret;
373+
374+ s->pic.reference = 1;
375+ s->pic.buffer_hints = FF_BUFFER_HINTS_VALID |
376+ FF_BUFFER_HINTS_PRESERVE |
377+ FF_BUFFER_HINTS_REUSABLE;
378+ if ((ret = avctx->reget_buffer(avctx, &s->pic))) {
379+ av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
380+ return ret;
381+ }
382+
383+ ftype = AV_RL32(avpkt->data);
384+ switch (ftype) {
385+ case 0:
386+ ret = xan_decode_frame_type0(avctx, avpkt);
387+ break;
388+ case 1:
389+ ret = xan_decode_frame_type1(avctx, avpkt);
390+ break;
391+ default:
392+ av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype);
393+ return -1;
394+ }
395+ if (ret)
396+ return ret;
397+
398+ *data_size = sizeof(AVFrame);
399+ *(AVFrame*)data = s->pic;
400+
401+ return avpkt->size;
402+}
403+
404+static av_cold int xan_decode_end(AVCodecContext *avctx)
405+{
406+ XanContext *s = avctx->priv_data;
407+
408+ if (s->pic.data[0])
409+ avctx->release_buffer(avctx, &s->pic);
410+
411+ av_freep(&s->y_buffer);
412+ av_freep(&s->scratch_buffer);
413+
414+ return 0;
415+}
416+
417+AVCodec ff_xan_wc4_decoder = {
418+ "xan_wc4",
419+ AVMEDIA_TYPE_VIDEO,
420+ CODEC_ID_XAN_WC4,
421+ sizeof(XanContext),
422+ xan_decode_init,
423+ NULL,
424+ xan_decode_end,
425+ xan_decode_frame,
426+ CODEC_CAP_DR1,
427+ .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
428+};
429+

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t