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