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