yading@10
|
1 /*
|
yading@10
|
2 * Wing Commander/Xan Video Decoder
|
yading@10
|
3 * Copyright (C) 2011 Konstantin Shishkov
|
yading@10
|
4 * based on work by Mike Melanson
|
yading@10
|
5 *
|
yading@10
|
6 * This file is part of FFmpeg.
|
yading@10
|
7 *
|
yading@10
|
8 * FFmpeg is free software; you can redistribute it and/or
|
yading@10
|
9 * modify it under the terms of the GNU Lesser General Public
|
yading@10
|
10 * License as published by the Free Software Foundation; either
|
yading@10
|
11 * version 2.1 of the License, or (at your option) any later version.
|
yading@10
|
12 *
|
yading@10
|
13 * FFmpeg is distributed in the hope that it will be useful,
|
yading@10
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
yading@10
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
yading@10
|
16 * Lesser General Public License for more details.
|
yading@10
|
17 *
|
yading@10
|
18 * You should have received a copy of the GNU Lesser General Public
|
yading@10
|
19 * License along with FFmpeg; if not, write to the Free Software
|
yading@10
|
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
yading@10
|
21 */
|
yading@10
|
22
|
yading@10
|
23 #include "avcodec.h"
|
yading@10
|
24 #include "libavutil/intreadwrite.h"
|
yading@10
|
25 #include "libavutil/mem.h"
|
yading@10
|
26 #include "bytestream.h"
|
yading@10
|
27 #define BITSTREAM_READER_LE
|
yading@10
|
28 #include "get_bits.h"
|
yading@10
|
29 #include "internal.h"
|
yading@10
|
30
|
yading@10
|
31 typedef struct XanContext {
|
yading@10
|
32 AVCodecContext *avctx;
|
yading@10
|
33 AVFrame *pic;
|
yading@10
|
34
|
yading@10
|
35 uint8_t *y_buffer;
|
yading@10
|
36 uint8_t *scratch_buffer;
|
yading@10
|
37 int buffer_size;
|
yading@10
|
38 GetByteContext gb;
|
yading@10
|
39 } XanContext;
|
yading@10
|
40
|
yading@10
|
41 static av_cold int xan_decode_end(AVCodecContext *avctx);
|
yading@10
|
42
|
yading@10
|
43 static av_cold int xan_decode_init(AVCodecContext *avctx)
|
yading@10
|
44 {
|
yading@10
|
45 XanContext *s = avctx->priv_data;
|
yading@10
|
46
|
yading@10
|
47 s->avctx = avctx;
|
yading@10
|
48
|
yading@10
|
49 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
|
yading@10
|
50
|
yading@10
|
51 if (avctx->height < 8) {
|
yading@10
|
52 av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height);
|
yading@10
|
53 return AVERROR(EINVAL);
|
yading@10
|
54 }
|
yading@10
|
55
|
yading@10
|
56 s->buffer_size = avctx->width * avctx->height;
|
yading@10
|
57 s->y_buffer = av_malloc(s->buffer_size);
|
yading@10
|
58 if (!s->y_buffer)
|
yading@10
|
59 return AVERROR(ENOMEM);
|
yading@10
|
60 s->scratch_buffer = av_malloc(s->buffer_size + 130);
|
yading@10
|
61 if (!s->scratch_buffer) {
|
yading@10
|
62 xan_decode_end(avctx);
|
yading@10
|
63 return AVERROR(ENOMEM);
|
yading@10
|
64 }
|
yading@10
|
65
|
yading@10
|
66 s->pic = av_frame_alloc();
|
yading@10
|
67 if (!s->pic) {
|
yading@10
|
68 xan_decode_end(avctx);
|
yading@10
|
69 return AVERROR(ENOMEM);
|
yading@10
|
70 }
|
yading@10
|
71
|
yading@10
|
72 return 0;
|
yading@10
|
73 }
|
yading@10
|
74
|
yading@10
|
75 static int xan_unpack_luma(XanContext *s,
|
yading@10
|
76 uint8_t *dst, const int dst_size)
|
yading@10
|
77 {
|
yading@10
|
78 int tree_size, eof;
|
yading@10
|
79 int bits, mask;
|
yading@10
|
80 int tree_root, node;
|
yading@10
|
81 const uint8_t *dst_end = dst + dst_size;
|
yading@10
|
82 GetByteContext tree = s->gb;
|
yading@10
|
83 int start_off = bytestream2_tell(&tree);
|
yading@10
|
84
|
yading@10
|
85 tree_size = bytestream2_get_byte(&s->gb);
|
yading@10
|
86 eof = bytestream2_get_byte(&s->gb);
|
yading@10
|
87 tree_root = eof + tree_size;
|
yading@10
|
88 bytestream2_skip(&s->gb, tree_size * 2);
|
yading@10
|
89
|
yading@10
|
90 node = tree_root;
|
yading@10
|
91 bits = bytestream2_get_byte(&s->gb);
|
yading@10
|
92 mask = 0x80;
|
yading@10
|
93 for (;;) {
|
yading@10
|
94 int bit = !!(bits & mask);
|
yading@10
|
95 mask >>= 1;
|
yading@10
|
96 bytestream2_seek(&tree, start_off + node*2 + bit - eof * 2, SEEK_SET);
|
yading@10
|
97 node = bytestream2_get_byte(&tree);
|
yading@10
|
98 if (node == eof)
|
yading@10
|
99 break;
|
yading@10
|
100 if (node < eof) {
|
yading@10
|
101 *dst++ = node;
|
yading@10
|
102 if (dst > dst_end)
|
yading@10
|
103 break;
|
yading@10
|
104 node = tree_root;
|
yading@10
|
105 }
|
yading@10
|
106 if (!mask) {
|
yading@10
|
107 if (bytestream2_get_bytes_left(&s->gb) <= 0)
|
yading@10
|
108 break;
|
yading@10
|
109 bits = bytestream2_get_byteu(&s->gb);
|
yading@10
|
110 mask = 0x80;
|
yading@10
|
111 }
|
yading@10
|
112 }
|
yading@10
|
113 return dst != dst_end ? AVERROR_INVALIDDATA : 0;
|
yading@10
|
114 }
|
yading@10
|
115
|
yading@10
|
116 /* almost the same as in xan_wc3 decoder */
|
yading@10
|
117 static int xan_unpack(XanContext *s,
|
yading@10
|
118 uint8_t *dest, const int dest_len)
|
yading@10
|
119 {
|
yading@10
|
120 uint8_t opcode;
|
yading@10
|
121 int size;
|
yading@10
|
122 uint8_t *orig_dest = dest;
|
yading@10
|
123 const uint8_t *dest_end = dest + dest_len;
|
yading@10
|
124
|
yading@10
|
125 while (dest < dest_end) {
|
yading@10
|
126 if (bytestream2_get_bytes_left(&s->gb) <= 0)
|
yading@10
|
127 return AVERROR_INVALIDDATA;
|
yading@10
|
128
|
yading@10
|
129 opcode = bytestream2_get_byteu(&s->gb);
|
yading@10
|
130
|
yading@10
|
131 if (opcode < 0xe0) {
|
yading@10
|
132 int size2, back;
|
yading@10
|
133 if ((opcode & 0x80) == 0) {
|
yading@10
|
134 size = opcode & 3;
|
yading@10
|
135 back = ((opcode & 0x60) << 3) + bytestream2_get_byte(&s->gb) + 1;
|
yading@10
|
136 size2 = ((opcode & 0x1c) >> 2) + 3;
|
yading@10
|
137 } else if ((opcode & 0x40) == 0) {
|
yading@10
|
138 size = bytestream2_peek_byte(&s->gb) >> 6;
|
yading@10
|
139 back = (bytestream2_get_be16(&s->gb) & 0x3fff) + 1;
|
yading@10
|
140 size2 = (opcode & 0x3f) + 4;
|
yading@10
|
141 } else {
|
yading@10
|
142 size = opcode & 3;
|
yading@10
|
143 back = ((opcode & 0x10) << 12) + bytestream2_get_be16(&s->gb) + 1;
|
yading@10
|
144 size2 = ((opcode & 0x0c) << 6) + bytestream2_get_byte(&s->gb) + 5;
|
yading@10
|
145 if (size + size2 > dest_end - dest)
|
yading@10
|
146 break;
|
yading@10
|
147 }
|
yading@10
|
148 if (dest + size + size2 > dest_end ||
|
yading@10
|
149 dest - orig_dest + size < back)
|
yading@10
|
150 return AVERROR_INVALIDDATA;
|
yading@10
|
151 bytestream2_get_buffer(&s->gb, dest, size);
|
yading@10
|
152 dest += size;
|
yading@10
|
153 av_memcpy_backptr(dest, back, size2);
|
yading@10
|
154 dest += size2;
|
yading@10
|
155 } else {
|
yading@10
|
156 int finish = opcode >= 0xfc;
|
yading@10
|
157
|
yading@10
|
158 size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
|
yading@10
|
159 if (dest_end - dest < size)
|
yading@10
|
160 return AVERROR_INVALIDDATA;
|
yading@10
|
161 bytestream2_get_buffer(&s->gb, dest, size);
|
yading@10
|
162 dest += size;
|
yading@10
|
163 if (finish)
|
yading@10
|
164 break;
|
yading@10
|
165 }
|
yading@10
|
166 }
|
yading@10
|
167 return dest - orig_dest;
|
yading@10
|
168 }
|
yading@10
|
169
|
yading@10
|
170 static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
|
yading@10
|
171 {
|
yading@10
|
172 XanContext *s = avctx->priv_data;
|
yading@10
|
173 uint8_t *U, *V;
|
yading@10
|
174 int val, uval, vval;
|
yading@10
|
175 int i, j;
|
yading@10
|
176 const uint8_t *src, *src_end;
|
yading@10
|
177 const uint8_t *table;
|
yading@10
|
178 int mode, offset, dec_size, table_size;
|
yading@10
|
179
|
yading@10
|
180 if (!chroma_off)
|
yading@10
|
181 return 0;
|
yading@10
|
182 if (chroma_off + 4 >= bytestream2_get_bytes_left(&s->gb)) {
|
yading@10
|
183 av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n");
|
yading@10
|
184 return AVERROR_INVALIDDATA;
|
yading@10
|
185 }
|
yading@10
|
186 bytestream2_seek(&s->gb, chroma_off + 4, SEEK_SET);
|
yading@10
|
187 mode = bytestream2_get_le16(&s->gb);
|
yading@10
|
188 table = s->gb.buffer;
|
yading@10
|
189 table_size = bytestream2_get_le16(&s->gb);
|
yading@10
|
190 offset = table_size * 2;
|
yading@10
|
191 table_size += 1;
|
yading@10
|
192
|
yading@10
|
193 if (offset >= bytestream2_get_bytes_left(&s->gb)) {
|
yading@10
|
194 av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n");
|
yading@10
|
195 return AVERROR_INVALIDDATA;
|
yading@10
|
196 }
|
yading@10
|
197
|
yading@10
|
198 bytestream2_skip(&s->gb, offset);
|
yading@10
|
199 memset(s->scratch_buffer, 0, s->buffer_size);
|
yading@10
|
200 dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size);
|
yading@10
|
201 if (dec_size < 0) {
|
yading@10
|
202 av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n");
|
yading@10
|
203 return dec_size;
|
yading@10
|
204 }
|
yading@10
|
205
|
yading@10
|
206 U = s->pic->data[1];
|
yading@10
|
207 V = s->pic->data[2];
|
yading@10
|
208 src = s->scratch_buffer;
|
yading@10
|
209 src_end = src + dec_size;
|
yading@10
|
210 if (mode) {
|
yading@10
|
211 for (j = 0; j < avctx->height >> 1; j++) {
|
yading@10
|
212 for (i = 0; i < avctx->width >> 1; i++) {
|
yading@10
|
213 if (src_end - src < 1)
|
yading@10
|
214 return 0;
|
yading@10
|
215 val = *src++;
|
yading@10
|
216 if (val) {
|
yading@10
|
217 if (val >= table_size)
|
yading@10
|
218 return AVERROR_INVALIDDATA;
|
yading@10
|
219 val = AV_RL16(table + (val << 1));
|
yading@10
|
220 uval = (val >> 3) & 0xF8;
|
yading@10
|
221 vval = (val >> 8) & 0xF8;
|
yading@10
|
222 U[i] = uval | (uval >> 5);
|
yading@10
|
223 V[i] = vval | (vval >> 5);
|
yading@10
|
224 }
|
yading@10
|
225 }
|
yading@10
|
226 U += s->pic->linesize[1];
|
yading@10
|
227 V += s->pic->linesize[2];
|
yading@10
|
228 }
|
yading@10
|
229 if (avctx->height & 1) {
|
yading@10
|
230 memcpy(U, U - s->pic->linesize[1], avctx->width >> 1);
|
yading@10
|
231 memcpy(V, V - s->pic->linesize[2], avctx->width >> 1);
|
yading@10
|
232 }
|
yading@10
|
233 } else {
|
yading@10
|
234 uint8_t *U2 = U + s->pic->linesize[1];
|
yading@10
|
235 uint8_t *V2 = V + s->pic->linesize[2];
|
yading@10
|
236
|
yading@10
|
237 for (j = 0; j < avctx->height >> 2; j++) {
|
yading@10
|
238 for (i = 0; i < avctx->width >> 1; i += 2) {
|
yading@10
|
239 if (src_end - src < 1)
|
yading@10
|
240 return 0;
|
yading@10
|
241 val = *src++;
|
yading@10
|
242 if (val) {
|
yading@10
|
243 if (val >= table_size)
|
yading@10
|
244 return AVERROR_INVALIDDATA;
|
yading@10
|
245 val = AV_RL16(table + (val << 1));
|
yading@10
|
246 uval = (val >> 3) & 0xF8;
|
yading@10
|
247 vval = (val >> 8) & 0xF8;
|
yading@10
|
248 U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5);
|
yading@10
|
249 V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
|
yading@10
|
250 }
|
yading@10
|
251 }
|
yading@10
|
252 U += s->pic->linesize[1] * 2;
|
yading@10
|
253 V += s->pic->linesize[2] * 2;
|
yading@10
|
254 U2 += s->pic->linesize[1] * 2;
|
yading@10
|
255 V2 += s->pic->linesize[2] * 2;
|
yading@10
|
256 }
|
yading@10
|
257 if (avctx->height & 3) {
|
yading@10
|
258 int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2;
|
yading@10
|
259
|
yading@10
|
260 memcpy(U, U - lines * s->pic->linesize[1], lines * s->pic->linesize[1]);
|
yading@10
|
261 memcpy(V, V - lines * s->pic->linesize[2], lines * s->pic->linesize[2]);
|
yading@10
|
262 }
|
yading@10
|
263 }
|
yading@10
|
264
|
yading@10
|
265 return 0;
|
yading@10
|
266 }
|
yading@10
|
267
|
yading@10
|
268 static int xan_decode_frame_type0(AVCodecContext *avctx)
|
yading@10
|
269 {
|
yading@10
|
270 XanContext *s = avctx->priv_data;
|
yading@10
|
271 uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer;
|
yading@10
|
272 unsigned chroma_off, corr_off;
|
yading@10
|
273 int cur, last;
|
yading@10
|
274 int i, j;
|
yading@10
|
275 int ret;
|
yading@10
|
276
|
yading@10
|
277 chroma_off = bytestream2_get_le32(&s->gb);
|
yading@10
|
278 corr_off = bytestream2_get_le32(&s->gb);
|
yading@10
|
279
|
yading@10
|
280 if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0)
|
yading@10
|
281 return ret;
|
yading@10
|
282
|
yading@10
|
283 if (corr_off >= bytestream2_size(&s->gb)) {
|
yading@10
|
284 av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
|
yading@10
|
285 corr_off = 0;
|
yading@10
|
286 }
|
yading@10
|
287 bytestream2_seek(&s->gb, 12, SEEK_SET);
|
yading@10
|
288 ret = xan_unpack_luma(s, src, s->buffer_size >> 1);
|
yading@10
|
289 if (ret) {
|
yading@10
|
290 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
|
yading@10
|
291 return ret;
|
yading@10
|
292 }
|
yading@10
|
293
|
yading@10
|
294 ybuf = s->y_buffer;
|
yading@10
|
295 last = *src++;
|
yading@10
|
296 ybuf[0] = last << 1;
|
yading@10
|
297 for (j = 1; j < avctx->width - 1; j += 2) {
|
yading@10
|
298 cur = (last + *src++) & 0x1F;
|
yading@10
|
299 ybuf[j] = last + cur;
|
yading@10
|
300 ybuf[j+1] = cur << 1;
|
yading@10
|
301 last = cur;
|
yading@10
|
302 }
|
yading@10
|
303 if(j < avctx->width)
|
yading@10
|
304 ybuf[j] = last << 1;
|
yading@10
|
305 prev_buf = ybuf;
|
yading@10
|
306 ybuf += avctx->width;
|
yading@10
|
307
|
yading@10
|
308 for (i = 1; i < avctx->height; i++) {
|
yading@10
|
309 last = ((prev_buf[0] >> 1) + *src++) & 0x1F;
|
yading@10
|
310 ybuf[0] = last << 1;
|
yading@10
|
311 for (j = 1; j < avctx->width - 1; j += 2) {
|
yading@10
|
312 cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F;
|
yading@10
|
313 ybuf[j] = last + cur;
|
yading@10
|
314 ybuf[j+1] = cur << 1;
|
yading@10
|
315 last = cur;
|
yading@10
|
316 }
|
yading@10
|
317 if(j < avctx->width)
|
yading@10
|
318 ybuf[j] = last << 1;
|
yading@10
|
319 prev_buf = ybuf;
|
yading@10
|
320 ybuf += avctx->width;
|
yading@10
|
321 }
|
yading@10
|
322
|
yading@10
|
323 if (corr_off) {
|
yading@10
|
324 int dec_size;
|
yading@10
|
325
|
yading@10
|
326 bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET);
|
yading@10
|
327 dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2);
|
yading@10
|
328 if (dec_size < 0)
|
yading@10
|
329 dec_size = 0;
|
yading@10
|
330 else
|
yading@10
|
331 dec_size = FFMIN(dec_size, s->buffer_size/2 - 1);
|
yading@10
|
332
|
yading@10
|
333 for (i = 0; i < dec_size; i++)
|
yading@10
|
334 s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
|
yading@10
|
335 }
|
yading@10
|
336
|
yading@10
|
337 src = s->y_buffer;
|
yading@10
|
338 ybuf = s->pic->data[0];
|
yading@10
|
339 for (j = 0; j < avctx->height; j++) {
|
yading@10
|
340 for (i = 0; i < avctx->width; i++)
|
yading@10
|
341 ybuf[i] = (src[i] << 2) | (src[i] >> 3);
|
yading@10
|
342 src += avctx->width;
|
yading@10
|
343 ybuf += s->pic->linesize[0];
|
yading@10
|
344 }
|
yading@10
|
345
|
yading@10
|
346 return 0;
|
yading@10
|
347 }
|
yading@10
|
348
|
yading@10
|
349 static int xan_decode_frame_type1(AVCodecContext *avctx)
|
yading@10
|
350 {
|
yading@10
|
351 XanContext *s = avctx->priv_data;
|
yading@10
|
352 uint8_t *ybuf, *src = s->scratch_buffer;
|
yading@10
|
353 int cur, last;
|
yading@10
|
354 int i, j;
|
yading@10
|
355 int ret;
|
yading@10
|
356
|
yading@10
|
357 if ((ret = xan_decode_chroma(avctx, bytestream2_get_le32(&s->gb))) != 0)
|
yading@10
|
358 return ret;
|
yading@10
|
359
|
yading@10
|
360 bytestream2_seek(&s->gb, 16, SEEK_SET);
|
yading@10
|
361 ret = xan_unpack_luma(s, src,
|
yading@10
|
362 s->buffer_size >> 1);
|
yading@10
|
363 if (ret) {
|
yading@10
|
364 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
|
yading@10
|
365 return ret;
|
yading@10
|
366 }
|
yading@10
|
367
|
yading@10
|
368 ybuf = s->y_buffer;
|
yading@10
|
369 for (i = 0; i < avctx->height; i++) {
|
yading@10
|
370 last = (ybuf[0] + (*src++ << 1)) & 0x3F;
|
yading@10
|
371 ybuf[0] = last;
|
yading@10
|
372 for (j = 1; j < avctx->width - 1; j += 2) {
|
yading@10
|
373 cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F;
|
yading@10
|
374 ybuf[j] = (last + cur) >> 1;
|
yading@10
|
375 ybuf[j+1] = cur;
|
yading@10
|
376 last = cur;
|
yading@10
|
377 }
|
yading@10
|
378 if(j < avctx->width)
|
yading@10
|
379 ybuf[j] = last;
|
yading@10
|
380 ybuf += avctx->width;
|
yading@10
|
381 }
|
yading@10
|
382
|
yading@10
|
383 src = s->y_buffer;
|
yading@10
|
384 ybuf = s->pic->data[0];
|
yading@10
|
385 for (j = 0; j < avctx->height; j++) {
|
yading@10
|
386 for (i = 0; i < avctx->width; i++)
|
yading@10
|
387 ybuf[i] = (src[i] << 2) | (src[i] >> 3);
|
yading@10
|
388 src += avctx->width;
|
yading@10
|
389 ybuf += s->pic->linesize[0];
|
yading@10
|
390 }
|
yading@10
|
391
|
yading@10
|
392 return 0;
|
yading@10
|
393 }
|
yading@10
|
394
|
yading@10
|
395 static int xan_decode_frame(AVCodecContext *avctx,
|
yading@10
|
396 void *data, int *got_frame,
|
yading@10
|
397 AVPacket *avpkt)
|
yading@10
|
398 {
|
yading@10
|
399 XanContext *s = avctx->priv_data;
|
yading@10
|
400 int ftype;
|
yading@10
|
401 int ret;
|
yading@10
|
402
|
yading@10
|
403 if ((ret = ff_reget_buffer(avctx, s->pic)) < 0)
|
yading@10
|
404 return ret;
|
yading@10
|
405
|
yading@10
|
406 bytestream2_init(&s->gb, avpkt->data, avpkt->size);
|
yading@10
|
407 ftype = bytestream2_get_le32(&s->gb);
|
yading@10
|
408 switch (ftype) {
|
yading@10
|
409 case 0:
|
yading@10
|
410 ret = xan_decode_frame_type0(avctx);
|
yading@10
|
411 break;
|
yading@10
|
412 case 1:
|
yading@10
|
413 ret = xan_decode_frame_type1(avctx);
|
yading@10
|
414 break;
|
yading@10
|
415 default:
|
yading@10
|
416 av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype);
|
yading@10
|
417 return AVERROR_INVALIDDATA;
|
yading@10
|
418 }
|
yading@10
|
419 if (ret)
|
yading@10
|
420 return ret;
|
yading@10
|
421
|
yading@10
|
422 if ((ret = av_frame_ref(data, s->pic)) < 0)
|
yading@10
|
423 return ret;
|
yading@10
|
424
|
yading@10
|
425 *got_frame = 1;
|
yading@10
|
426
|
yading@10
|
427 return avpkt->size;
|
yading@10
|
428 }
|
yading@10
|
429
|
yading@10
|
430 static av_cold int xan_decode_end(AVCodecContext *avctx)
|
yading@10
|
431 {
|
yading@10
|
432 XanContext *s = avctx->priv_data;
|
yading@10
|
433
|
yading@10
|
434 av_frame_free(&s->pic);
|
yading@10
|
435
|
yading@10
|
436 av_freep(&s->y_buffer);
|
yading@10
|
437 av_freep(&s->scratch_buffer);
|
yading@10
|
438
|
yading@10
|
439 return 0;
|
yading@10
|
440 }
|
yading@10
|
441
|
yading@10
|
442 AVCodec ff_xan_wc4_decoder = {
|
yading@10
|
443 .name = "xan_wc4",
|
yading@10
|
444 .type = AVMEDIA_TYPE_VIDEO,
|
yading@10
|
445 .id = AV_CODEC_ID_XAN_WC4,
|
yading@10
|
446 .priv_data_size = sizeof(XanContext),
|
yading@10
|
447 .init = xan_decode_init,
|
yading@10
|
448 .close = xan_decode_end,
|
yading@10
|
449 .decode = xan_decode_frame,
|
yading@10
|
450 .capabilities = CODEC_CAP_DR1,
|
yading@10
|
451 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
|
yading@10
|
452 };
|