2 * Wing Commander/Xan Video Decoder
3 * Copyright (C) 2011 Konstantin Shishkov
4 * based on work by Mike Melanson
6 * This file is part of FFmpeg.
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.
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.
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
24 #include "libavutil/intreadwrite.h"
25 #include "libavutil/mem.h"
26 #include "bytestream.h"
27 #define BITSTREAM_READER_LE
31 typedef struct XanContext
{
32 AVCodecContext
*avctx
;
36 uint8_t *scratch_buffer
;
41 static av_cold
int xan_decode_end(AVCodecContext
*avctx
)
43 XanContext
*s
= avctx
->priv_data
;
45 av_frame_free(&s
->pic
);
47 av_freep(&s
->y_buffer
);
48 av_freep(&s
->scratch_buffer
);
53 static av_cold
int xan_decode_init(AVCodecContext
*avctx
)
55 XanContext
*s
= avctx
->priv_data
;
59 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P
;
61 if (avctx
->height
< 8) {
62 av_log(avctx
, AV_LOG_ERROR
, "Invalid frame height: %d.\n", avctx
->height
);
63 return AVERROR(EINVAL
);
65 if (avctx
->width
& 1) {
66 av_log(avctx
, AV_LOG_ERROR
, "Invalid frame width: %d.\n", avctx
->width
);
67 return AVERROR(EINVAL
);
70 s
->buffer_size
= avctx
->width
* avctx
->height
;
71 s
->y_buffer
= av_malloc(s
->buffer_size
);
73 return AVERROR(ENOMEM
);
74 s
->scratch_buffer
= av_malloc(s
->buffer_size
+ 130);
75 if (!s
->scratch_buffer
) {
76 xan_decode_end(avctx
);
77 return AVERROR(ENOMEM
);
80 s
->pic
= av_frame_alloc();
82 xan_decode_end(avctx
);
83 return AVERROR(ENOMEM
);
89 static int xan_unpack_luma(XanContext
*s
,
90 uint8_t *dst
, const int dst_size
)
95 const uint8_t *dst_end
= dst
+ dst_size
;
96 GetByteContext tree
= s
->gb
;
97 int start_off
= bytestream2_tell(&tree
);
99 tree_size
= bytestream2_get_byte(&s
->gb
);
100 eof
= bytestream2_get_byte(&s
->gb
);
101 tree_root
= eof
+ tree_size
;
102 bytestream2_skip(&s
->gb
, tree_size
* 2);
105 bits
= bytestream2_get_byte(&s
->gb
);
108 int bit
= !!(bits
& mask
);
110 bytestream2_seek(&tree
, start_off
+ node
*2 + bit
- eof
* 2, SEEK_SET
);
111 node
= bytestream2_get_byte(&tree
);
121 if (bytestream2_get_bytes_left(&s
->gb
) <= 0)
123 bits
= bytestream2_get_byteu(&s
->gb
);
127 return dst
!= dst_end
? AVERROR_INVALIDDATA
: 0;
130 /* almost the same as in xan_wc3 decoder */
131 static int xan_unpack(XanContext
*s
,
132 uint8_t *dest
, const int dest_len
)
136 uint8_t *orig_dest
= dest
;
137 const uint8_t *dest_end
= dest
+ dest_len
;
139 while (dest
< dest_end
) {
140 if (bytestream2_get_bytes_left(&s
->gb
) <= 0)
141 return AVERROR_INVALIDDATA
;
143 opcode
= bytestream2_get_byteu(&s
->gb
);
147 if ((opcode
& 0x80) == 0) {
149 back
= ((opcode
& 0x60) << 3) + bytestream2_get_byte(&s
->gb
) + 1;
150 size2
= ((opcode
& 0x1c) >> 2) + 3;
151 } else if ((opcode
& 0x40) == 0) {
152 size
= bytestream2_peek_byte(&s
->gb
) >> 6;
153 back
= (bytestream2_get_be16(&s
->gb
) & 0x3fff) + 1;
154 size2
= (opcode
& 0x3f) + 4;
157 back
= ((opcode
& 0x10) << 12) + bytestream2_get_be16(&s
->gb
) + 1;
158 size2
= ((opcode
& 0x0c) << 6) + bytestream2_get_byte(&s
->gb
) + 5;
159 if (size
+ size2
> dest_end
- dest
)
162 if (dest
+ size
+ size2
> dest_end
||
163 dest
- orig_dest
+ size
< back
)
164 return AVERROR_INVALIDDATA
;
165 bytestream2_get_buffer(&s
->gb
, dest
, size
);
167 av_memcpy_backptr(dest
, back
, size2
);
170 int finish
= opcode
>= 0xfc;
172 size
= finish
? opcode
& 3 : ((opcode
& 0x1f) << 2) + 4;
173 if (dest_end
- dest
< size
)
174 return AVERROR_INVALIDDATA
;
175 bytestream2_get_buffer(&s
->gb
, dest
, size
);
181 return dest
- orig_dest
;
184 static int xan_decode_chroma(AVCodecContext
*avctx
, unsigned chroma_off
)
186 XanContext
*s
= avctx
->priv_data
;
190 const uint8_t *src
, *src_end
;
191 const uint8_t *table
;
192 int mode
, offset
, dec_size
, table_size
;
196 if (chroma_off
+ 4 >= bytestream2_get_bytes_left(&s
->gb
)) {
197 av_log(avctx
, AV_LOG_ERROR
, "Invalid chroma block position\n");
198 return AVERROR_INVALIDDATA
;
200 bytestream2_seek(&s
->gb
, chroma_off
+ 4, SEEK_SET
);
201 mode
= bytestream2_get_le16(&s
->gb
);
202 table
= s
->gb
.buffer
;
203 table_size
= bytestream2_get_le16(&s
->gb
);
204 offset
= table_size
* 2;
207 if (offset
>= bytestream2_get_bytes_left(&s
->gb
)) {
208 av_log(avctx
, AV_LOG_ERROR
, "Invalid chroma block offset\n");
209 return AVERROR_INVALIDDATA
;
212 bytestream2_skip(&s
->gb
, offset
);
213 memset(s
->scratch_buffer
, 0, s
->buffer_size
);
214 dec_size
= xan_unpack(s
, s
->scratch_buffer
, s
->buffer_size
);
216 av_log(avctx
, AV_LOG_ERROR
, "Chroma unpacking failed\n");
222 src
= s
->scratch_buffer
;
223 src_end
= src
+ dec_size
;
225 for (j
= 0; j
< avctx
->height
>> 1; j
++) {
226 for (i
= 0; i
< avctx
->width
>> 1; i
++) {
227 if (src_end
- src
< 1)
231 if (val
>= table_size
)
232 return AVERROR_INVALIDDATA
;
233 val
= AV_RL16(table
+ (val
<< 1));
234 uval
= (val
>> 3) & 0xF8;
235 vval
= (val
>> 8) & 0xF8;
236 U
[i
] = uval
| (uval
>> 5);
237 V
[i
] = vval
| (vval
>> 5);
240 U
+= s
->pic
->linesize
[1];
241 V
+= s
->pic
->linesize
[2];
243 if (avctx
->height
& 1) {
244 memcpy(U
, U
- s
->pic
->linesize
[1], avctx
->width
>> 1);
245 memcpy(V
, V
- s
->pic
->linesize
[2], avctx
->width
>> 1);
248 uint8_t *U2
= U
+ s
->pic
->linesize
[1];
249 uint8_t *V2
= V
+ s
->pic
->linesize
[2];
251 for (j
= 0; j
< avctx
->height
>> 2; j
++) {
252 for (i
= 0; i
< avctx
->width
>> 1; i
+= 2) {
253 if (src_end
- src
< 1)
257 if (val
>= table_size
)
258 return AVERROR_INVALIDDATA
;
259 val
= AV_RL16(table
+ (val
<< 1));
260 uval
= (val
>> 3) & 0xF8;
261 vval
= (val
>> 8) & 0xF8;
262 U
[i
] = U
[i
+1] = U2
[i
] = U2
[i
+1] = uval
| (uval
>> 5);
263 V
[i
] = V
[i
+1] = V2
[i
] = V2
[i
+1] = vval
| (vval
>> 5);
266 U
+= s
->pic
->linesize
[1] * 2;
267 V
+= s
->pic
->linesize
[2] * 2;
268 U2
+= s
->pic
->linesize
[1] * 2;
269 V2
+= s
->pic
->linesize
[2] * 2;
271 if (avctx
->height
& 3) {
272 int lines
= ((avctx
->height
+ 1) >> 1) - (avctx
->height
>> 2) * 2;
274 memcpy(U
, U
- lines
* s
->pic
->linesize
[1], lines
* s
->pic
->linesize
[1]);
275 memcpy(V
, V
- lines
* s
->pic
->linesize
[2], lines
* s
->pic
->linesize
[2]);
282 static int xan_decode_frame_type0(AVCodecContext
*avctx
)
284 XanContext
*s
= avctx
->priv_data
;
285 uint8_t *ybuf
, *prev_buf
, *src
= s
->scratch_buffer
;
286 unsigned chroma_off
, corr_off
;
291 chroma_off
= bytestream2_get_le32(&s
->gb
);
292 corr_off
= bytestream2_get_le32(&s
->gb
);
294 if ((ret
= xan_decode_chroma(avctx
, chroma_off
)) != 0)
297 if (corr_off
>= bytestream2_size(&s
->gb
)) {
298 av_log(avctx
, AV_LOG_WARNING
, "Ignoring invalid correction block position\n");
301 bytestream2_seek(&s
->gb
, 12, SEEK_SET
);
302 ret
= xan_unpack_luma(s
, src
, s
->buffer_size
>> 1);
304 av_log(avctx
, AV_LOG_ERROR
, "Luma decoding failed\n");
311 for (j
= 1; j
< avctx
->width
- 1; j
+= 2) {
312 cur
= (last
+ *src
++) & 0x1F;
313 ybuf
[j
] = last
+ cur
;
314 ybuf
[j
+1] = cur
<< 1;
319 ybuf
+= avctx
->width
;
321 for (i
= 1; i
< avctx
->height
; i
++) {
322 last
= ((prev_buf
[0] >> 1) + *src
++) & 0x1F;
324 for (j
= 1; j
< avctx
->width
- 1; j
+= 2) {
325 cur
= ((prev_buf
[j
+ 1] >> 1) + *src
++) & 0x1F;
326 ybuf
[j
] = last
+ cur
;
327 ybuf
[j
+1] = cur
<< 1;
332 ybuf
+= avctx
->width
;
338 bytestream2_seek(&s
->gb
, 8 + corr_off
, SEEK_SET
);
339 dec_size
= xan_unpack(s
, s
->scratch_buffer
, s
->buffer_size
/ 2);
343 dec_size
= FFMIN(dec_size
, s
->buffer_size
/2 - 1);
345 for (i
= 0; i
< dec_size
; i
++)
346 s
->y_buffer
[i
*2+1] = (s
->y_buffer
[i
*2+1] + (s
->scratch_buffer
[i
] << 1)) & 0x3F;
350 ybuf
= s
->pic
->data
[0];
351 for (j
= 0; j
< avctx
->height
; j
++) {
352 for (i
= 0; i
< avctx
->width
; i
++)
353 ybuf
[i
] = (src
[i
] << 2) | (src
[i
] >> 3);
355 ybuf
+= s
->pic
->linesize
[0];
361 static int xan_decode_frame_type1(AVCodecContext
*avctx
)
363 XanContext
*s
= avctx
->priv_data
;
364 uint8_t *ybuf
, *src
= s
->scratch_buffer
;
369 if ((ret
= xan_decode_chroma(avctx
, bytestream2_get_le32(&s
->gb
))) != 0)
372 bytestream2_seek(&s
->gb
, 16, SEEK_SET
);
373 ret
= xan_unpack_luma(s
, src
,
374 s
->buffer_size
>> 1);
376 av_log(avctx
, AV_LOG_ERROR
, "Luma decoding failed\n");
381 for (i
= 0; i
< avctx
->height
; i
++) {
382 last
= (ybuf
[0] + (*src
++ << 1)) & 0x3F;
384 for (j
= 1; j
< avctx
->width
- 1; j
+= 2) {
385 cur
= (ybuf
[j
+ 1] + (*src
++ << 1)) & 0x3F;
386 ybuf
[j
] = (last
+ cur
) >> 1;
391 ybuf
+= avctx
->width
;
395 ybuf
= s
->pic
->data
[0];
396 for (j
= 0; j
< avctx
->height
; j
++) {
397 for (i
= 0; i
< avctx
->width
; i
++)
398 ybuf
[i
] = (src
[i
] << 2) | (src
[i
] >> 3);
400 ybuf
+= s
->pic
->linesize
[0];
406 static int xan_decode_frame(AVCodecContext
*avctx
,
407 void *data
, int *got_frame
,
410 XanContext
*s
= avctx
->priv_data
;
414 if ((ret
= ff_reget_buffer(avctx
, s
->pic
)) < 0)
417 bytestream2_init(&s
->gb
, avpkt
->data
, avpkt
->size
);
418 ftype
= bytestream2_get_le32(&s
->gb
);
421 ret
= xan_decode_frame_type0(avctx
);
424 ret
= xan_decode_frame_type1(avctx
);
427 av_log(avctx
, AV_LOG_ERROR
, "Unknown frame type %d\n", ftype
);
428 return AVERROR_INVALIDDATA
;
433 if ((ret
= av_frame_ref(data
, s
->pic
)) < 0)
441 AVCodec ff_xan_wc4_decoder
= {
443 .long_name
= NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
444 .type
= AVMEDIA_TYPE_VIDEO
,
445 .id
= AV_CODEC_ID_XAN_WC4
,
446 .priv_data_size
= sizeof(XanContext
),
447 .init
= xan_decode_init
,
448 .close
= xan_decode_end
,
449 .decode
= xan_decode_frame
,
450 .capabilities
= CODEC_CAP_DR1
,