1 /*
2 * Wing Commander/Xan Video Decoder
3 * Copyright (C) 2003 The FFmpeg project
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * Xan video decoder for Wing Commander III computer game
25 * by Mario Brito (mbrito@student.dei.uc.pt)
26 * and Mike Melanson (melanson@pcisys.net)
27 *
28 * The xan_wc3 decoder outputs PAL8 data.
29 */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "libavutil/intreadwrite.h"
36 #include "libavutil/mem.h"
37
38 #define BITSTREAM_READER_LE
39 #include "avcodec.h"
40 #include "bytestream.h"
41 #include "get_bits.h"
42 #include "internal.h"
43
44 #define RUNTIME_GAMMA 0
45
46 #define VGA__TAG MKTAG('V', 'G', 'A', ' ')
47 #define PALT_TAG MKTAG('P', 'A', 'L', 'T')
48 #define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
49 #define PALETTE_COUNT 256
50 #define PALETTE_SIZE (PALETTE_COUNT * 3)
51 #define PALETTES_MAX 256
52
53 typedef struct XanContext {
54
55 AVCodecContext *avctx;
56 AVFrame *last_frame;
57
58 const uint8_t *buf;
59 int size;
60
61 /* scratch space */
62 uint8_t *buffer1;
63 int buffer1_size;
64 uint8_t *buffer2;
65 int buffer2_size;
66
67 unsigned *palettes;
68 int palettes_count;
69 int cur_palette;
70
71 int frame_size;
72
73 } XanContext;
74
xan_decode_end(AVCodecContext * avctx)75 static av_cold int xan_decode_end(AVCodecContext *avctx)
76 {
77 XanContext *s = avctx->priv_data;
78
79 av_frame_free(&s->last_frame);
80
81 av_freep(&s->buffer1);
82 av_freep(&s->buffer2);
83 av_freep(&s->palettes);
84
85 return 0;
86 }
87
xan_decode_init(AVCodecContext * avctx)88 static av_cold int xan_decode_init(AVCodecContext *avctx)
89 {
90 XanContext *s = avctx->priv_data;
91
92 s->avctx = avctx;
93 s->frame_size = 0;
94
95 avctx->pix_fmt = AV_PIX_FMT_PAL8;
96
97 s->buffer1_size = avctx->width * avctx->height;
98 s->buffer1 = av_malloc(s->buffer1_size);
99 if (!s->buffer1)
100 return AVERROR(ENOMEM);
101 s->buffer2_size = avctx->width * avctx->height;
102 s->buffer2 = av_malloc(s->buffer2_size + 130);
103 if (!s->buffer2)
104 return AVERROR(ENOMEM);
105
106 s->last_frame = av_frame_alloc();
107 if (!s->last_frame)
108 return AVERROR(ENOMEM);
109
110 return 0;
111 }
112
xan_huffman_decode(uint8_t * dest,int dest_len,const uint8_t * src,int src_len)113 static int xan_huffman_decode(uint8_t *dest, int dest_len,
114 const uint8_t *src, int src_len)
115 {
116 uint8_t byte = *src++;
117 uint8_t ival = byte + 0x16;
118 const uint8_t * ptr = src + byte*2;
119 int ptr_len = src_len - 1 - byte*2;
120 uint8_t val = ival;
121 uint8_t *dest_end = dest + dest_len;
122 uint8_t *dest_start = dest;
123 int ret;
124 GetBitContext gb;
125
126 if ((ret = init_get_bits8(&gb, ptr, ptr_len)) < 0)
127 return ret;
128
129 while (val != 0x16) {
130 unsigned idx;
131 if (get_bits_left(&gb) < 1)
132 return AVERROR_INVALIDDATA;
133 idx = val - 0x17 + get_bits1(&gb) * byte;
134 if (idx >= 2 * byte)
135 return AVERROR_INVALIDDATA;
136 val = src[idx];
137
138 if (val < 0x16) {
139 if (dest >= dest_end)
140 return dest_len;
141 *dest++ = val;
142 val = ival;
143 }
144 }
145
146 return dest - dest_start;
147 }
148
149 /**
150 * unpack simple compression
151 *
152 * @param dest destination buffer of dest_len, must be padded with at least 130 bytes
153 */
xan_unpack(uint8_t * dest,int dest_len,const uint8_t * src,int src_len)154 static void xan_unpack(uint8_t *dest, int dest_len,
155 const uint8_t *src, int src_len)
156 {
157 uint8_t opcode;
158 int size;
159 uint8_t *dest_org = dest;
160 uint8_t *dest_end = dest + dest_len;
161 GetByteContext ctx;
162
163 bytestream2_init(&ctx, src, src_len);
164 while (dest < dest_end && bytestream2_get_bytes_left(&ctx)) {
165 opcode = bytestream2_get_byte(&ctx);
166
167 if (opcode < 0xe0) {
168 int size2, back;
169 if ((opcode & 0x80) == 0) {
170 size = opcode & 3;
171
172 back = ((opcode & 0x60) << 3) + bytestream2_get_byte(&ctx) + 1;
173 size2 = ((opcode & 0x1c) >> 2) + 3;
174 } else if ((opcode & 0x40) == 0) {
175 size = bytestream2_peek_byte(&ctx) >> 6;
176
177 back = (bytestream2_get_be16(&ctx) & 0x3fff) + 1;
178 size2 = (opcode & 0x3f) + 4;
179 } else {
180 size = opcode & 3;
181
182 back = ((opcode & 0x10) << 12) + bytestream2_get_be16(&ctx) + 1;
183 size2 = ((opcode & 0x0c) << 6) + bytestream2_get_byte(&ctx) + 5;
184 }
185
186 if (dest_end - dest < size + size2 ||
187 dest + size - dest_org < back ||
188 bytestream2_get_bytes_left(&ctx) < size)
189 return;
190 bytestream2_get_buffer(&ctx, dest, size);
191 dest += size;
192 av_memcpy_backptr(dest, back, size2);
193 dest += size2;
194 } else {
195 int finish = opcode >= 0xfc;
196 size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
197
198 if (dest_end - dest < size || bytestream2_get_bytes_left(&ctx) < size)
199 return;
200 bytestream2_get_buffer(&ctx, dest, size);
201 dest += size;
202 if (finish)
203 return;
204 }
205 }
206 }
207
xan_wc3_output_pixel_run(XanContext * s,AVFrame * frame,const uint8_t * pixel_buffer,int x,int y,int pixel_count)208 static inline void xan_wc3_output_pixel_run(XanContext *s, AVFrame *frame,
209 const uint8_t *pixel_buffer, int x, int y, int pixel_count)
210 {
211 int stride;
212 int line_inc;
213 int index;
214 int current_x;
215 int width = s->avctx->width;
216 uint8_t *palette_plane;
217
218 palette_plane = frame->data[0];
219 stride = frame->linesize[0];
220 line_inc = stride - width;
221 index = y * stride + x;
222 current_x = x;
223 while (pixel_count && index < s->frame_size) {
224 int count = FFMIN(pixel_count, width - current_x);
225 memcpy(palette_plane + index, pixel_buffer, count);
226 pixel_count -= count;
227 index += count;
228 pixel_buffer += count;
229 current_x += count;
230
231 if (current_x >= width) {
232 index += line_inc;
233 current_x = 0;
234 }
235 }
236 }
237
xan_wc3_copy_pixel_run(XanContext * s,AVFrame * frame,int x,int y,int pixel_count,int motion_x,int motion_y)238 static inline void xan_wc3_copy_pixel_run(XanContext *s, AVFrame *frame,
239 int x, int y,
240 int pixel_count, int motion_x,
241 int motion_y)
242 {
243 int stride;
244 int line_inc;
245 int curframe_index, prevframe_index;
246 int curframe_x, prevframe_x;
247 int width = s->avctx->width;
248 uint8_t *palette_plane, *prev_palette_plane;
249
250 if (y + motion_y < 0 || y + motion_y >= s->avctx->height ||
251 x + motion_x < 0 || x + motion_x >= s->avctx->width)
252 return;
253
254 palette_plane = frame->data[0];
255 prev_palette_plane = s->last_frame->data[0];
256 if (!prev_palette_plane)
257 prev_palette_plane = palette_plane;
258 stride = frame->linesize[0];
259 line_inc = stride - width;
260 curframe_index = y * stride + x;
261 curframe_x = x;
262 prevframe_index = (y + motion_y) * stride + x + motion_x;
263 prevframe_x = x + motion_x;
264
265 if (prev_palette_plane == palette_plane && FFABS(motion_x + width*motion_y) < pixel_count) {
266 avpriv_request_sample(s->avctx, "Overlapping copy");
267 return ;
268 }
269
270 while (pixel_count &&
271 curframe_index < s->frame_size &&
272 prevframe_index < s->frame_size) {
273 int count = FFMIN3(pixel_count, width - curframe_x,
274 width - prevframe_x);
275
276 memcpy(palette_plane + curframe_index,
277 prev_palette_plane + prevframe_index, count);
278 pixel_count -= count;
279 curframe_index += count;
280 prevframe_index += count;
281 curframe_x += count;
282 prevframe_x += count;
283
284 if (curframe_x >= width) {
285 curframe_index += line_inc;
286 curframe_x = 0;
287 }
288
289 if (prevframe_x >= width) {
290 prevframe_index += line_inc;
291 prevframe_x = 0;
292 }
293 }
294 }
295
xan_wc3_decode_frame(XanContext * s,AVFrame * frame)296 static int xan_wc3_decode_frame(XanContext *s, AVFrame *frame)
297 {
298
299 int width = s->avctx->width;
300 int height = s->avctx->height;
301 int total_pixels = width * height;
302 uint8_t opcode;
303 uint8_t flag = 0;
304 int size = 0;
305 int motion_x, motion_y;
306 int x, y, ret;
307
308 uint8_t *opcode_buffer = s->buffer1;
309 uint8_t *opcode_buffer_end = s->buffer1 + s->buffer1_size;
310 int opcode_buffer_size = s->buffer1_size;
311 const uint8_t *imagedata_buffer = s->buffer2;
312
313 /* pointers to segments inside the compressed chunk */
314 const uint8_t *huffman_segment;
315 GetByteContext size_segment;
316 GetByteContext vector_segment;
317 const uint8_t *imagedata_segment;
318 int huffman_offset, size_offset, vector_offset, imagedata_offset,
319 imagedata_size;
320
321 if (s->size < 8)
322 return AVERROR_INVALIDDATA;
323
324 huffman_offset = AV_RL16(&s->buf[0]);
325 size_offset = AV_RL16(&s->buf[2]);
326 vector_offset = AV_RL16(&s->buf[4]);
327 imagedata_offset = AV_RL16(&s->buf[6]);
328
329 if (huffman_offset >= s->size ||
330 size_offset >= s->size ||
331 vector_offset >= s->size ||
332 imagedata_offset >= s->size)
333 return AVERROR_INVALIDDATA;
334
335 huffman_segment = s->buf + huffman_offset;
336 bytestream2_init(&size_segment, s->buf + size_offset, s->size - size_offset);
337 bytestream2_init(&vector_segment, s->buf + vector_offset, s->size - vector_offset);
338 imagedata_segment = s->buf + imagedata_offset;
339
340 if ((ret = xan_huffman_decode(opcode_buffer, opcode_buffer_size,
341 huffman_segment, s->size - huffman_offset)) < 0)
342 return AVERROR_INVALIDDATA;
343 opcode_buffer_end = opcode_buffer + ret;
344
345 if (imagedata_segment[0] == 2) {
346 xan_unpack(s->buffer2, s->buffer2_size,
347 &imagedata_segment[1], s->size - imagedata_offset - 1);
348 imagedata_size = s->buffer2_size;
349 } else {
350 imagedata_size = s->size - imagedata_offset - 1;
351 imagedata_buffer = &imagedata_segment[1];
352 }
353
354 /* use the decoded data segments to build the frame */
355 x = y = 0;
356 while (total_pixels && opcode_buffer < opcode_buffer_end) {
357
358 opcode = *opcode_buffer++;
359 size = 0;
360
361 switch (opcode) {
362
363 case 0:
364 flag ^= 1;
365 continue;
366
367 case 1:
368 case 2:
369 case 3:
370 case 4:
371 case 5:
372 case 6:
373 case 7:
374 case 8:
375 size = opcode;
376 break;
377
378 case 12:
379 case 13:
380 case 14:
381 case 15:
382 case 16:
383 case 17:
384 case 18:
385 size += (opcode - 10);
386 break;
387
388 case 9:
389 case 19:
390 if (bytestream2_get_bytes_left(&size_segment) < 1) {
391 av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
392 return AVERROR_INVALIDDATA;
393 }
394 size = bytestream2_get_byte(&size_segment);
395 break;
396
397 case 10:
398 case 20:
399 if (bytestream2_get_bytes_left(&size_segment) < 2) {
400 av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
401 return AVERROR_INVALIDDATA;
402 }
403 size = bytestream2_get_be16(&size_segment);
404 break;
405
406 case 11:
407 case 21:
408 if (bytestream2_get_bytes_left(&size_segment) < 3) {
409 av_log(s->avctx, AV_LOG_ERROR, "size_segment overread\n");
410 return AVERROR_INVALIDDATA;
411 }
412 size = bytestream2_get_be24(&size_segment);
413 break;
414 }
415
416 if (size > total_pixels)
417 break;
418
419 if (opcode < 12) {
420 flag ^= 1;
421 if (flag) {
422 /* run of (size) pixels is unchanged from last frame */
423 xan_wc3_copy_pixel_run(s, frame, x, y, size, 0, 0);
424 } else {
425 /* output a run of pixels from imagedata_buffer */
426 if (imagedata_size < size)
427 break;
428 xan_wc3_output_pixel_run(s, frame, imagedata_buffer, x, y, size);
429 imagedata_buffer += size;
430 imagedata_size -= size;
431 }
432 } else {
433 uint8_t vector;
434 if (bytestream2_get_bytes_left(&vector_segment) <= 0) {
435 av_log(s->avctx, AV_LOG_ERROR, "vector_segment overread\n");
436 return AVERROR_INVALIDDATA;
437 }
438 /* run-based motion compensation from last frame */
439 vector = bytestream2_get_byte(&vector_segment);
440 motion_x = sign_extend(vector >> 4, 4);
441 motion_y = sign_extend(vector & 0xF, 4);
442
443 /* copy a run of pixels from the previous frame */
444 xan_wc3_copy_pixel_run(s, frame, x, y, size, motion_x, motion_y);
445
446 flag = 0;
447 }
448
449 /* coordinate accounting */
450 total_pixels -= size;
451 y += (x + size) / width;
452 x = (x + size) % width;
453 }
454 return 0;
455 }
456
457 #if RUNTIME_GAMMA
mul(unsigned a,unsigned b)458 static inline unsigned mul(unsigned a, unsigned b)
459 {
460 return (a * b) >> 16;
461 }
462
pow4(unsigned a)463 static inline unsigned pow4(unsigned a)
464 {
465 unsigned square = mul(a, a);
466 return mul(square, square);
467 }
468
pow5(unsigned a)469 static inline unsigned pow5(unsigned a)
470 {
471 return mul(pow4(a), a);
472 }
473
gamma_corr(uint8_t in)474 static uint8_t gamma_corr(uint8_t in) {
475 unsigned lo, hi = 0xff40, target;
476 int i = 15;
477 in = (in << 2) | (in >> 6);
478 /* equivalent float code:
479 if (in >= 252)
480 return 253;
481 return round(pow(in / 256.0, 0.8) * 256);
482 */
483 lo = target = in << 8;
484 do {
485 unsigned mid = (lo + hi) >> 1;
486 unsigned pow = pow5(mid);
487 if (pow > target) hi = mid;
488 else lo = mid;
489 } while (--i);
490 return (pow4((lo + hi) >> 1) + 0x80) >> 8;
491 }
492 #else
493 /**
494 * This is a gamma correction that xan3 applies to all palette entries.
495 *
496 * There is a peculiarity, namely that the values are clamped to 253 -
497 * it seems likely that this table was calculated by a buggy fixed-point
498 * implementation, the one above under RUNTIME_GAMMA behaves like this for
499 * example.
500 * The exponent value of 0.8 can be explained by this as well, since 0.8 = 4/5
501 * and thus pow(x, 0.8) is still easy to calculate.
502 * Also, the input values are first rotated to the left by 2.
503 */
504 static const uint8_t gamma_lookup[256] = {
505 0x00, 0x09, 0x10, 0x16, 0x1C, 0x21, 0x27, 0x2C,
506 0x31, 0x35, 0x3A, 0x3F, 0x43, 0x48, 0x4C, 0x50,
507 0x54, 0x59, 0x5D, 0x61, 0x65, 0x69, 0x6D, 0x71,
508 0x75, 0x79, 0x7D, 0x80, 0x84, 0x88, 0x8C, 0x8F,
509 0x93, 0x97, 0x9A, 0x9E, 0xA2, 0xA5, 0xA9, 0xAC,
510 0xB0, 0xB3, 0xB7, 0xBA, 0xBE, 0xC1, 0xC5, 0xC8,
511 0xCB, 0xCF, 0xD2, 0xD5, 0xD9, 0xDC, 0xDF, 0xE3,
512 0xE6, 0xE9, 0xED, 0xF0, 0xF3, 0xF6, 0xFA, 0xFD,
513 0x03, 0x0B, 0x12, 0x18, 0x1D, 0x23, 0x28, 0x2D,
514 0x32, 0x36, 0x3B, 0x40, 0x44, 0x49, 0x4D, 0x51,
515 0x56, 0x5A, 0x5E, 0x62, 0x66, 0x6A, 0x6E, 0x72,
516 0x76, 0x7A, 0x7D, 0x81, 0x85, 0x89, 0x8D, 0x90,
517 0x94, 0x98, 0x9B, 0x9F, 0xA2, 0xA6, 0xAA, 0xAD,
518 0xB1, 0xB4, 0xB8, 0xBB, 0xBF, 0xC2, 0xC5, 0xC9,
519 0xCC, 0xD0, 0xD3, 0xD6, 0xDA, 0xDD, 0xE0, 0xE4,
520 0xE7, 0xEA, 0xED, 0xF1, 0xF4, 0xF7, 0xFA, 0xFD,
521 0x05, 0x0D, 0x13, 0x19, 0x1F, 0x24, 0x29, 0x2E,
522 0x33, 0x38, 0x3C, 0x41, 0x45, 0x4A, 0x4E, 0x52,
523 0x57, 0x5B, 0x5F, 0x63, 0x67, 0x6B, 0x6F, 0x73,
524 0x77, 0x7B, 0x7E, 0x82, 0x86, 0x8A, 0x8D, 0x91,
525 0x95, 0x99, 0x9C, 0xA0, 0xA3, 0xA7, 0xAA, 0xAE,
526 0xB2, 0xB5, 0xB9, 0xBC, 0xBF, 0xC3, 0xC6, 0xCA,
527 0xCD, 0xD0, 0xD4, 0xD7, 0xDA, 0xDE, 0xE1, 0xE4,
528 0xE8, 0xEB, 0xEE, 0xF1, 0xF5, 0xF8, 0xFB, 0xFD,
529 0x07, 0x0E, 0x15, 0x1A, 0x20, 0x25, 0x2A, 0x2F,
530 0x34, 0x39, 0x3D, 0x42, 0x46, 0x4B, 0x4F, 0x53,
531 0x58, 0x5C, 0x60, 0x64, 0x68, 0x6C, 0x70, 0x74,
532 0x78, 0x7C, 0x7F, 0x83, 0x87, 0x8B, 0x8E, 0x92,
533 0x96, 0x99, 0x9D, 0xA1, 0xA4, 0xA8, 0xAB, 0xAF,
534 0xB2, 0xB6, 0xB9, 0xBD, 0xC0, 0xC4, 0xC7, 0xCB,
535 0xCE, 0xD1, 0xD5, 0xD8, 0xDB, 0xDF, 0xE2, 0xE5,
536 0xE9, 0xEC, 0xEF, 0xF2, 0xF6, 0xF9, 0xFC, 0xFD
537 };
538 #endif
539
xan_decode_frame(AVCodecContext * avctx,void * data,int * got_frame,AVPacket * avpkt)540 static int xan_decode_frame(AVCodecContext *avctx,
541 void *data, int *got_frame,
542 AVPacket *avpkt)
543 {
544 AVFrame *frame = data;
545 const uint8_t *buf = avpkt->data;
546 int ret, buf_size = avpkt->size;
547 XanContext *s = avctx->priv_data;
548 GetByteContext ctx;
549 int tag = 0;
550
551 bytestream2_init(&ctx, buf, buf_size);
552 while (bytestream2_get_bytes_left(&ctx) > 8 && tag != VGA__TAG) {
553 unsigned *tmpptr;
554 uint32_t new_pal;
555 int size;
556 int i;
557 tag = bytestream2_get_le32(&ctx);
558 size = bytestream2_get_be32(&ctx);
559 if (size < 0) {
560 av_log(avctx, AV_LOG_ERROR, "Invalid tag size %d\n", size);
561 return AVERROR_INVALIDDATA;
562 }
563 size = FFMIN(size, bytestream2_get_bytes_left(&ctx));
564 switch (tag) {
565 case PALT_TAG:
566 if (size < PALETTE_SIZE)
567 return AVERROR_INVALIDDATA;
568 if (s->palettes_count >= PALETTES_MAX)
569 return AVERROR_INVALIDDATA;
570 tmpptr = av_realloc_array(s->palettes,
571 s->palettes_count + 1, AVPALETTE_SIZE);
572 if (!tmpptr)
573 return AVERROR(ENOMEM);
574 s->palettes = tmpptr;
575 tmpptr += s->palettes_count * AVPALETTE_COUNT;
576 for (i = 0; i < PALETTE_COUNT; i++) {
577 #if RUNTIME_GAMMA
578 int r = gamma_corr(bytestream2_get_byteu(&ctx));
579 int g = gamma_corr(bytestream2_get_byteu(&ctx));
580 int b = gamma_corr(bytestream2_get_byteu(&ctx));
581 #else
582 int r = gamma_lookup[bytestream2_get_byteu(&ctx)];
583 int g = gamma_lookup[bytestream2_get_byteu(&ctx)];
584 int b = gamma_lookup[bytestream2_get_byteu(&ctx)];
585 #endif
586 *tmpptr++ = (0xFFU << 24) | (r << 16) | (g << 8) | b;
587 }
588 s->palettes_count++;
589 break;
590 case SHOT_TAG:
591 if (size < 4)
592 return AVERROR_INVALIDDATA;
593 new_pal = bytestream2_get_le32(&ctx);
594 if (new_pal < s->palettes_count) {
595 s->cur_palette = new_pal;
596 } else
597 av_log(avctx, AV_LOG_ERROR, "Invalid palette selected\n");
598 break;
599 case VGA__TAG:
600 break;
601 default:
602 bytestream2_skip(&ctx, size);
603 break;
604 }
605 }
606 buf_size = bytestream2_get_bytes_left(&ctx);
607
608 if (s->palettes_count <= 0) {
609 av_log(s->avctx, AV_LOG_ERROR, "No palette found\n");
610 return AVERROR_INVALIDDATA;
611 }
612
613 if ((ret = ff_get_buffer(avctx, frame, AV_GET_BUFFER_FLAG_REF)) < 0)
614 return ret;
615
616 if (!s->frame_size)
617 s->frame_size = frame->linesize[0] * s->avctx->height;
618
619 memcpy(frame->data[1],
620 s->palettes + s->cur_palette * AVPALETTE_COUNT, AVPALETTE_SIZE);
621
622 s->buf = ctx.buffer;
623 s->size = buf_size;
624
625 if (xan_wc3_decode_frame(s, frame) < 0)
626 return AVERROR_INVALIDDATA;
627
628 av_frame_unref(s->last_frame);
629 if ((ret = av_frame_ref(s->last_frame, frame)) < 0)
630 return ret;
631
632 *got_frame = 1;
633
634 /* always report that the buffer was completely consumed */
635 return buf_size;
636 }
637
638 AVCodec ff_xan_wc3_decoder = {
639 .name = "xan_wc3",
640 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander III / Xan"),
641 .type = AVMEDIA_TYPE_VIDEO,
642 .id = AV_CODEC_ID_XAN_WC3,
643 .priv_data_size = sizeof(XanContext),
644 .init = xan_decode_init,
645 .close = xan_decode_end,
646 .decode = xan_decode_frame,
647 .capabilities = AV_CODEC_CAP_DR1,
648 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_INIT_THREADSAFE,
649 };
650