xxan.c
Go to the documentation of this file.
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 "libavutil/mem.h"
26 #include "bytestream.h"
27 #define BITSTREAM_READER_LE
28 #include "get_bits.h"
29 #include "internal.h"
30 
31 typedef struct XanContext {
34 
39 } XanContext;
40 
42 
44 {
45  XanContext *s = avctx->priv_data;
46 
47  s->avctx = avctx;
48 
49  avctx->pix_fmt = AV_PIX_FMT_YUV420P;
50 
51  if (avctx->height < 8) {
52  av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height);
53  return AVERROR(EINVAL);
54  }
55 
56  s->buffer_size = avctx->width * avctx->height;
58  if (!s->y_buffer)
59  return AVERROR(ENOMEM);
60  s->scratch_buffer = av_malloc(s->buffer_size + 130);
61  if (!s->scratch_buffer) {
62  xan_decode_end(avctx);
63  return AVERROR(ENOMEM);
64  }
65 
66  s->pic = av_frame_alloc();
67  if (!s->pic) {
68  xan_decode_end(avctx);
69  return AVERROR(ENOMEM);
70  }
71 
72  return 0;
73 }
74 
76  uint8_t *dst, const int dst_size)
77 {
78  int tree_size, eof;
79  int bits, mask;
80  int tree_root, node;
81  const uint8_t *dst_end = dst + dst_size;
82  GetByteContext tree = s->gb;
83  int start_off = bytestream2_tell(&tree);
84 
85  tree_size = bytestream2_get_byte(&s->gb);
86  eof = bytestream2_get_byte(&s->gb);
87  tree_root = eof + tree_size;
88  bytestream2_skip(&s->gb, tree_size * 2);
89 
90  node = tree_root;
91  bits = bytestream2_get_byte(&s->gb);
92  mask = 0x80;
93  for (;;) {
94  int bit = !!(bits & mask);
95  mask >>= 1;
96  bytestream2_seek(&tree, start_off + node*2 + bit - eof * 2, SEEK_SET);
97  node = bytestream2_get_byte(&tree);
98  if (node == eof)
99  break;
100  if (node < eof) {
101  *dst++ = node;
102  if (dst > dst_end)
103  break;
104  node = tree_root;
105  }
106  if (!mask) {
107  if (bytestream2_get_bytes_left(&s->gb) <= 0)
108  break;
109  bits = bytestream2_get_byteu(&s->gb);
110  mask = 0x80;
111  }
112  }
113  return dst != dst_end ? AVERROR_INVALIDDATA : 0;
114 }
115 
116 /* almost the same as in xan_wc3 decoder */
117 static int xan_unpack(XanContext *s,
118  uint8_t *dest, const int dest_len)
119 {
120  uint8_t opcode;
121  int size;
122  uint8_t *orig_dest = dest;
123  const uint8_t *dest_end = dest + dest_len;
124 
125  while (dest < dest_end) {
126  if (bytestream2_get_bytes_left(&s->gb) <= 0)
127  return AVERROR_INVALIDDATA;
128 
129  opcode = bytestream2_get_byteu(&s->gb);
130 
131  if (opcode < 0xe0) {
132  int size2, back;
133  if ((opcode & 0x80) == 0) {
134  size = opcode & 3;
135  back = ((opcode & 0x60) << 3) + bytestream2_get_byte(&s->gb) + 1;
136  size2 = ((opcode & 0x1c) >> 2) + 3;
137  } else if ((opcode & 0x40) == 0) {
138  size = bytestream2_peek_byte(&s->gb) >> 6;
139  back = (bytestream2_get_be16(&s->gb) & 0x3fff) + 1;
140  size2 = (opcode & 0x3f) + 4;
141  } else {
142  size = opcode & 3;
143  back = ((opcode & 0x10) << 12) + bytestream2_get_be16(&s->gb) + 1;
144  size2 = ((opcode & 0x0c) << 6) + bytestream2_get_byte(&s->gb) + 5;
145  if (size + size2 > dest_end - dest)
146  break;
147  }
148  if (dest + size + size2 > dest_end ||
149  dest - orig_dest + size < back)
150  return AVERROR_INVALIDDATA;
151  bytestream2_get_buffer(&s->gb, dest, size);
152  dest += size;
153  av_memcpy_backptr(dest, back, size2);
154  dest += size2;
155  } else {
156  int finish = opcode >= 0xfc;
157 
158  size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
159  if (dest_end - dest < size)
160  return AVERROR_INVALIDDATA;
161  bytestream2_get_buffer(&s->gb, dest, size);
162  dest += size;
163  if (finish)
164  break;
165  }
166  }
167  return dest - orig_dest;
168 }
169 
170 static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
171 {
172  XanContext *s = avctx->priv_data;
173  uint8_t *U, *V;
174  int val, uval, vval;
175  int i, j;
176  const uint8_t *src, *src_end;
177  const uint8_t *table;
178  int mode, offset, dec_size, table_size;
179 
180  if (!chroma_off)
181  return 0;
182  if (chroma_off + 4 >= bytestream2_get_bytes_left(&s->gb)) {
183  av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n");
184  return AVERROR_INVALIDDATA;
185  }
186  bytestream2_seek(&s->gb, chroma_off + 4, SEEK_SET);
187  mode = bytestream2_get_le16(&s->gb);
188  table = s->gb.buffer;
189  table_size = bytestream2_get_le16(&s->gb);
190  offset = table_size * 2;
191  table_size += 1;
192 
193  if (offset >= bytestream2_get_bytes_left(&s->gb)) {
194  av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n");
195  return AVERROR_INVALIDDATA;
196  }
197 
198  bytestream2_skip(&s->gb, offset);
199  memset(s->scratch_buffer, 0, s->buffer_size);
200  dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size);
201  if (dec_size < 0) {
202  av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n");
203  return dec_size;
204  }
205 
206  U = s->pic->data[1];
207  V = s->pic->data[2];
208  src = s->scratch_buffer;
209  src_end = src + dec_size;
210  if (mode) {
211  for (j = 0; j < avctx->height >> 1; j++) {
212  for (i = 0; i < avctx->width >> 1; i++) {
213  if (src_end - src < 1)
214  return 0;
215  val = *src++;
216  if (val) {
217  if (val >= table_size)
218  return AVERROR_INVALIDDATA;
219  val = AV_RL16(table + (val << 1));
220  uval = (val >> 3) & 0xF8;
221  vval = (val >> 8) & 0xF8;
222  U[i] = uval | (uval >> 5);
223  V[i] = vval | (vval >> 5);
224  }
225  }
226  U += s->pic->linesize[1];
227  V += s->pic->linesize[2];
228  }
229  if (avctx->height & 1) {
230  memcpy(U, U - s->pic->linesize[1], avctx->width >> 1);
231  memcpy(V, V - s->pic->linesize[2], avctx->width >> 1);
232  }
233  } else {
234  uint8_t *U2 = U + s->pic->linesize[1];
235  uint8_t *V2 = V + s->pic->linesize[2];
236 
237  for (j = 0; j < avctx->height >> 2; j++) {
238  for (i = 0; i < avctx->width >> 1; i += 2) {
239  if (src_end - src < 1)
240  return 0;
241  val = *src++;
242  if (val) {
243  if (val >= table_size)
244  return AVERROR_INVALIDDATA;
245  val = AV_RL16(table + (val << 1));
246  uval = (val >> 3) & 0xF8;
247  vval = (val >> 8) & 0xF8;
248  U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5);
249  V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
250  }
251  }
252  U += s->pic->linesize[1] * 2;
253  V += s->pic->linesize[2] * 2;
254  U2 += s->pic->linesize[1] * 2;
255  V2 += s->pic->linesize[2] * 2;
256  }
257  if (avctx->height & 3) {
258  int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2;
259 
260  memcpy(U, U - lines * s->pic->linesize[1], lines * s->pic->linesize[1]);
261  memcpy(V, V - lines * s->pic->linesize[2], lines * s->pic->linesize[2]);
262  }
263  }
264 
265  return 0;
266 }
267 
269 {
270  XanContext *s = avctx->priv_data;
271  uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer;
272  unsigned chroma_off, corr_off;
273  int cur, last;
274  int i, j;
275  int ret;
276 
277  chroma_off = bytestream2_get_le32(&s->gb);
278  corr_off = bytestream2_get_le32(&s->gb);
279 
280  if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0)
281  return ret;
282 
283  if (corr_off >= bytestream2_size(&s->gb)) {
284  av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
285  corr_off = 0;
286  }
287  bytestream2_seek(&s->gb, 12, SEEK_SET);
288  ret = xan_unpack_luma(s, src, s->buffer_size >> 1);
289  if (ret) {
290  av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
291  return ret;
292  }
293 
294  ybuf = s->y_buffer;
295  last = *src++;
296  ybuf[0] = last << 1;
297  for (j = 1; j < avctx->width - 1; j += 2) {
298  cur = (last + *src++) & 0x1F;
299  ybuf[j] = last + cur;
300  ybuf[j+1] = cur << 1;
301  last = cur;
302  }
303  if(j < avctx->width)
304  ybuf[j] = last << 1;
305  prev_buf = ybuf;
306  ybuf += avctx->width;
307 
308  for (i = 1; i < avctx->height; i++) {
309  last = ((prev_buf[0] >> 1) + *src++) & 0x1F;
310  ybuf[0] = last << 1;
311  for (j = 1; j < avctx->width - 1; j += 2) {
312  cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F;
313  ybuf[j] = last + cur;
314  ybuf[j+1] = cur << 1;
315  last = cur;
316  }
317  if(j < avctx->width)
318  ybuf[j] = last << 1;
319  prev_buf = ybuf;
320  ybuf += avctx->width;
321  }
322 
323  if (corr_off) {
324  int dec_size;
325 
326  bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET);
327  dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2);
328  if (dec_size < 0)
329  dec_size = 0;
330  else
331  dec_size = FFMIN(dec_size, s->buffer_size/2 - 1);
332 
333  for (i = 0; i < dec_size; i++)
334  s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
335  }
336 
337  src = s->y_buffer;
338  ybuf = s->pic->data[0];
339  for (j = 0; j < avctx->height; j++) {
340  for (i = 0; i < avctx->width; i++)
341  ybuf[i] = (src[i] << 2) | (src[i] >> 3);
342  src += avctx->width;
343  ybuf += s->pic->linesize[0];
344  }
345 
346  return 0;
347 }
348 
350 {
351  XanContext *s = avctx->priv_data;
352  uint8_t *ybuf, *src = s->scratch_buffer;
353  int cur, last;
354  int i, j;
355  int ret;
356 
357  if ((ret = xan_decode_chroma(avctx, bytestream2_get_le32(&s->gb))) != 0)
358  return ret;
359 
360  bytestream2_seek(&s->gb, 16, SEEK_SET);
361  ret = xan_unpack_luma(s, src,
362  s->buffer_size >> 1);
363  if (ret) {
364  av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
365  return ret;
366  }
367 
368  ybuf = s->y_buffer;
369  for (i = 0; i < avctx->height; i++) {
370  last = (ybuf[0] + (*src++ << 1)) & 0x3F;
371  ybuf[0] = last;
372  for (j = 1; j < avctx->width - 1; j += 2) {
373  cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F;
374  ybuf[j] = (last + cur) >> 1;
375  ybuf[j+1] = cur;
376  last = cur;
377  }
378  if(j < avctx->width)
379  ybuf[j] = last;
380  ybuf += avctx->width;
381  }
382 
383  src = s->y_buffer;
384  ybuf = s->pic->data[0];
385  for (j = 0; j < avctx->height; j++) {
386  for (i = 0; i < avctx->width; i++)
387  ybuf[i] = (src[i] << 2) | (src[i] >> 3);
388  src += avctx->width;
389  ybuf += s->pic->linesize[0];
390  }
391 
392  return 0;
393 }
394 
396  void *data, int *got_frame,
397  AVPacket *avpkt)
398 {
399  XanContext *s = avctx->priv_data;
400  int ftype;
401  int ret;
402 
403  if ((ret = ff_reget_buffer(avctx, s->pic)) < 0)
404  return ret;
405 
406  bytestream2_init(&s->gb, avpkt->data, avpkt->size);
407  ftype = bytestream2_get_le32(&s->gb);
408  switch (ftype) {
409  case 0:
410  ret = xan_decode_frame_type0(avctx);
411  break;
412  case 1:
413  ret = xan_decode_frame_type1(avctx);
414  break;
415  default:
416  av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype);
417  return AVERROR_INVALIDDATA;
418  }
419  if (ret)
420  return ret;
421 
422  if ((ret = av_frame_ref(data, s->pic)) < 0)
423  return ret;
424 
425  *got_frame = 1;
426 
427  return avpkt->size;
428 }
429 
431 {
432  XanContext *s = avctx->priv_data;
433 
434  av_frame_free(&s->pic);
435 
436  av_freep(&s->y_buffer);
438 
439  return 0;
440 }
441 
443  .name = "xan_wc4",
444  .type = AVMEDIA_TYPE_VIDEO,
445  .id = AV_CODEC_ID_XAN_WC4,
446  .priv_data_size = sizeof(XanContext),
450  .capabilities = CODEC_CAP_DR1,
451  .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
452 };
const char * s
Definition: avisynth_c.h:668
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
This structure describes decoded (raw) audio or video data.
Definition: frame.h:76
memory handling functions
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
static av_always_inline void bytestream2_init(GetByteContext *g, const uint8_t *buf, int buf_size)
Definition: bytestream.h:130
#define AV_RL16
AVCodec ff_xan_wc4_decoder
Definition: xxan.c:442
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:198
uint8_t bits
Definition: crc.c:216
uint8_t
#define av_cold
Definition: attributes.h:78
static int xan_decode_frame_type0(AVCodecContext *avctx)
Definition: xxan.c:268
mode
Definition: f_perms.c:27
#define CODEC_CAP_DR1
Codec uses get_buffer() for allocating buffers and supports custom allocators.
uint8_t * data
const uint8_t * buffer
Definition: bytestream.h:33
bitstream reader API header.
static av_always_inline int bytestream2_size(GetByteContext *g)
Definition: bytestream.h:193
#define U(x)
static const uint16_t mask[17]
Definition: lzw.c:37
static av_always_inline void bytestream2_skip(GetByteContext *g, unsigned int size)
Definition: bytestream.h:159
static const struct endianess table[]
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Spectrum Plot time data
static av_always_inline unsigned int bytestream2_get_buffer(GetByteContext *g, uint8_t *dst, unsigned int size)
Definition: bytestream.h:258
static av_always_inline unsigned int bytestream2_get_bytes_left(GetByteContext *g)
Definition: bytestream.h:149
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
const char * name
Name of the codec implementation.
static const uint8_t offset[127][2]
Definition: vf_spp.c:70
external API header
uint8_t * y_buffer
Definition: xxan.c:35
int size
Definition: xan.c:58
#define V
int ff_reget_buffer(AVCodecContext *avctx, AVFrame *frame)
Identical in function to av_frame_make_writable(), except it uses ff_get_buffer() to allocate the buf...
uint8_t * scratch_buffer
Definition: xxan.c:36
#define FFMIN(a, b)
Definition: common.h:58
ret
Definition: avfilter.c:821
int width
picture width / height.
static int xan_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: xxan.c:395
static av_always_inline int bytestream2_tell(GetByteContext *g)
Definition: bytestream.h:183
static av_cold int xan_decode_end(AVCodecContext *avctx)
Definition: xxan.c:430
static int width
Definition: tests/utils.c:158
dest
Definition: start.py:60
AVS_Value src
Definition: avisynth_c.h:523
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:101
main external API structure.
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:375
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
Definition: xan.c:52
void * av_malloc(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:73
synthesis window for stochastic i
static int xan_unpack_luma(XanContext *s, uint8_t *dst, const int dst_size)
Definition: xxan.c:75
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static av_cold int xan_decode_init(AVCodecContext *avctx)
Definition: xxan.c:43
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:95
int av_frame_ref(AVFrame *dst, AVFrame *src)
Setup a new reference to the data described by an given frame.
Definition: frame.c:228
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:87
int buffer_size
Definition: xxan.c:37
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:68
common internal api header.
struct XanContext XanContext
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:108
static int xan_decode_frame_type1(AVCodecContext *avctx)
Definition: xxan.c:349
static int xan_unpack(XanContext *s, uint8_t *dest, const int dest_len)
Definition: xxan.c:117
else dst[i][x+y *dst_stride[i]]
Definition: vf_mcdeint.c:160
static av_always_inline int bytestream2_seek(GetByteContext *g, int offset, int whence)
Definition: bytestream.h:203
AVFrame * pic
Definition: xxan.c:33
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
deliberately overlapping memcpy implementation
Definition: mem.c:327
static int decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt)
Definition: crystalhd.c:868
GetByteContext gb
Definition: xxan.c:38
This structure stores compressed data.
AVCodecContext * avctx
Definition: xan.c:54
static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
Definition: xxan.c:170