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 Libav.
8 * Libav 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 * Libav 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 Libav; 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
30 typedef struct XanContext
{
31 AVCodecContext
*avctx
;
35 uint8_t *scratch_buffer
;
40 static av_cold
int xan_decode_init(AVCodecContext
*avctx
)
42 XanContext
*s
= avctx
->priv_data
;
46 avctx
->pix_fmt
= AV_PIX_FMT_YUV420P
;
48 if (avctx
->height
< 8) {
49 av_log(avctx
, AV_LOG_ERROR
, "Invalid frame height: %d.\n", avctx
->height
);
50 return AVERROR(EINVAL
);
53 s
->buffer_size
= avctx
->width
* avctx
->height
;
54 s
->y_buffer
= av_malloc(s
->buffer_size
);
56 return AVERROR(ENOMEM
);
57 s
->scratch_buffer
= av_malloc(s
->buffer_size
+ 130);
58 if (!s
->scratch_buffer
) {
59 av_freep(&s
->y_buffer
);
60 return AVERROR(ENOMEM
);
66 static int xan_unpack_luma(XanContext
*s
,
67 uint8_t *dst
, const int dst_size
)
72 const uint8_t *dst_end
= dst
+ dst_size
;
73 GetByteContext tree
= s
->gb
;
74 int start_off
= bytestream2_tell(&tree
);
76 tree_size
= bytestream2_get_byte(&s
->gb
);
77 eof
= bytestream2_get_byte(&s
->gb
);
78 tree_root
= eof
+ tree_size
;
79 bytestream2_skip(&s
->gb
, tree_size
* 2);
82 bits
= bytestream2_get_byte(&s
->gb
);
85 int bit
= !!(bits
& mask
);
87 bytestream2_seek(&tree
, start_off
+ node
*2 + bit
- eof
* 2, SEEK_SET
);
88 node
= bytestream2_get_byte(&tree
);
98 if (bytestream2_get_bytes_left(&s
->gb
) <= 0)
100 bits
= bytestream2_get_byteu(&s
->gb
);
104 return dst
!= dst_end
? AVERROR_INVALIDDATA
: 0;
107 /* almost the same as in xan_wc3 decoder */
108 static int xan_unpack(XanContext
*s
,
109 uint8_t *dest
, const int dest_len
)
113 uint8_t *orig_dest
= dest
;
114 const uint8_t *dest_end
= dest
+ dest_len
;
116 while (dest
< dest_end
) {
117 if (bytestream2_get_bytes_left(&s
->gb
) <= 0)
118 return AVERROR_INVALIDDATA
;
120 opcode
= bytestream2_get_byteu(&s
->gb
);
124 if ((opcode
& 0x80) == 0) {
126 back
= ((opcode
& 0x60) << 3) + bytestream2_get_byte(&s
->gb
) + 1;
127 size2
= ((opcode
& 0x1c) >> 2) + 3;
128 } else if ((opcode
& 0x40) == 0) {
129 size
= bytestream2_peek_byte(&s
->gb
) >> 6;
130 back
= (bytestream2_get_be16(&s
->gb
) & 0x3fff) + 1;
131 size2
= (opcode
& 0x3f) + 4;
134 back
= ((opcode
& 0x10) << 12) + bytestream2_get_be16(&s
->gb
) + 1;
135 size2
= ((opcode
& 0x0c) << 6) + bytestream2_get_byte(&s
->gb
) + 5;
136 if (size
+ size2
> dest_end
- dest
)
139 if (dest
+ size
+ size2
> dest_end
||
140 dest
- orig_dest
+ size
< back
)
141 return AVERROR_INVALIDDATA
;
142 bytestream2_get_buffer(&s
->gb
, dest
, size
);
144 av_memcpy_backptr(dest
, back
, size2
);
147 int finish
= opcode
>= 0xfc;
149 size
= finish
? opcode
& 3 : ((opcode
& 0x1f) << 2) + 4;
150 if (dest_end
- dest
< size
)
151 return AVERROR_INVALIDDATA
;
152 bytestream2_get_buffer(&s
->gb
, dest
, size
);
158 return dest
- orig_dest
;
161 static int xan_decode_chroma(AVCodecContext
*avctx
, unsigned chroma_off
)
163 XanContext
*s
= avctx
->priv_data
;
167 const uint8_t *src
, *src_end
;
168 const uint8_t *table
;
169 int mode
, offset
, dec_size
, table_size
;
173 if (chroma_off
+ 4 >= bytestream2_get_bytes_left(&s
->gb
)) {
174 av_log(avctx
, AV_LOG_ERROR
, "Invalid chroma block position\n");
175 return AVERROR_INVALIDDATA
;
177 bytestream2_seek(&s
->gb
, chroma_off
+ 4, SEEK_SET
);
178 mode
= bytestream2_get_le16(&s
->gb
);
179 table
= s
->gb
.buffer
;
180 table_size
= bytestream2_get_le16(&s
->gb
);
181 offset
= table_size
* 2;
184 if (offset
>= bytestream2_get_bytes_left(&s
->gb
)) {
185 av_log(avctx
, AV_LOG_ERROR
, "Invalid chroma block offset\n");
186 return AVERROR_INVALIDDATA
;
189 bytestream2_skip(&s
->gb
, offset
);
190 memset(s
->scratch_buffer
, 0, s
->buffer_size
);
191 dec_size
= xan_unpack(s
, s
->scratch_buffer
, s
->buffer_size
);
193 av_log(avctx
, AV_LOG_ERROR
, "Chroma unpacking failed\n");
199 src
= s
->scratch_buffer
;
200 src_end
= src
+ dec_size
;
202 for (j
= 0; j
< avctx
->height
>> 1; j
++) {
203 for (i
= 0; i
< avctx
->width
>> 1; i
++) {
205 if (val
&& val
< table_size
) {
206 val
= AV_RL16(table
+ (val
<< 1));
207 uval
= (val
>> 3) & 0xF8;
208 vval
= (val
>> 8) & 0xF8;
209 U
[i
] = uval
| (uval
>> 5);
210 V
[i
] = vval
| (vval
>> 5);
215 U
+= s
->pic
.linesize
[1];
216 V
+= s
->pic
.linesize
[2];
218 if (avctx
->height
& 1) {
219 memcpy(U
, U
- s
->pic
.linesize
[1], avctx
->width
>> 1);
220 memcpy(V
, V
- s
->pic
.linesize
[2], avctx
->width
>> 1);
223 uint8_t *U2
= U
+ s
->pic
.linesize
[1];
224 uint8_t *V2
= V
+ s
->pic
.linesize
[2];
226 for (j
= 0; j
< avctx
->height
>> 2; j
++) {
227 for (i
= 0; i
< avctx
->width
>> 1; i
+= 2) {
229 if (val
&& val
< table_size
) {
230 val
= AV_RL16(table
+ (val
<< 1));
231 uval
= (val
>> 3) & 0xF8;
232 vval
= (val
>> 8) & 0xF8;
233 U
[i
] = U
[i
+1] = U2
[i
] = U2
[i
+1] = uval
| (uval
>> 5);
234 V
[i
] = V
[i
+1] = V2
[i
] = V2
[i
+1] = vval
| (vval
>> 5);
237 U
+= s
->pic
.linesize
[1] * 2;
238 V
+= s
->pic
.linesize
[2] * 2;
239 U2
+= s
->pic
.linesize
[1] * 2;
240 V2
+= s
->pic
.linesize
[2] * 2;
242 if (avctx
->height
& 3) {
243 int lines
= ((avctx
->height
+ 1) >> 1) - (avctx
->height
>> 2) * 2;
245 memcpy(U
, U
- lines
* s
->pic
.linesize
[1], lines
* s
->pic
.linesize
[1]);
246 memcpy(V
, V
- lines
* s
->pic
.linesize
[2], lines
* s
->pic
.linesize
[2]);
253 static int xan_decode_frame_type0(AVCodecContext
*avctx
)
255 XanContext
*s
= avctx
->priv_data
;
256 uint8_t *ybuf
, *prev_buf
, *src
= s
->scratch_buffer
;
257 unsigned chroma_off
, corr_off
;
262 chroma_off
= bytestream2_get_le32(&s
->gb
);
263 corr_off
= bytestream2_get_le32(&s
->gb
);
265 if ((ret
= xan_decode_chroma(avctx
, chroma_off
)) != 0)
268 if (corr_off
>= (s
->gb
.buffer_end
- s
->gb
.buffer_start
)) {
269 av_log(avctx
, AV_LOG_WARNING
, "Ignoring invalid correction block position\n");
272 bytestream2_seek(&s
->gb
, 12, SEEK_SET
);
273 ret
= xan_unpack_luma(s
, src
, s
->buffer_size
>> 1);
275 av_log(avctx
, AV_LOG_ERROR
, "Luma decoding failed\n");
282 for (j
= 1; j
< avctx
->width
- 1; j
+= 2) {
283 cur
= (last
+ *src
++) & 0x1F;
284 ybuf
[j
] = last
+ cur
;
285 ybuf
[j
+1] = cur
<< 1;
290 ybuf
+= avctx
->width
;
292 for (i
= 1; i
< avctx
->height
; i
++) {
293 last
= ((prev_buf
[0] >> 1) + *src
++) & 0x1F;
295 for (j
= 1; j
< avctx
->width
- 1; j
+= 2) {
296 cur
= ((prev_buf
[j
+ 1] >> 1) + *src
++) & 0x1F;
297 ybuf
[j
] = last
+ cur
;
298 ybuf
[j
+1] = cur
<< 1;
303 ybuf
+= avctx
->width
;
309 bytestream2_seek(&s
->gb
, 8 + corr_off
, SEEK_SET
);
310 dec_size
= xan_unpack(s
, s
->scratch_buffer
, s
->buffer_size
);
313 for (i
= 0; i
< dec_size
; i
++)
314 s
->y_buffer
[i
*2+1] = (s
->y_buffer
[i
*2+1] + (s
->scratch_buffer
[i
] << 1)) & 0x3F;
318 ybuf
= s
->pic
.data
[0];
319 for (j
= 0; j
< avctx
->height
; j
++) {
320 for (i
= 0; i
< avctx
->width
; i
++)
321 ybuf
[i
] = (src
[i
] << 2) | (src
[i
] >> 3);
323 ybuf
+= s
->pic
.linesize
[0];
329 static int xan_decode_frame_type1(AVCodecContext
*avctx
)
331 XanContext
*s
= avctx
->priv_data
;
332 uint8_t *ybuf
, *src
= s
->scratch_buffer
;
337 if ((ret
= xan_decode_chroma(avctx
, bytestream2_get_le32(&s
->gb
))) != 0)
340 bytestream2_seek(&s
->gb
, 16, SEEK_SET
);
341 ret
= xan_unpack_luma(s
, src
,
342 s
->buffer_size
>> 1);
344 av_log(avctx
, AV_LOG_ERROR
, "Luma decoding failed\n");
349 for (i
= 0; i
< avctx
->height
; i
++) {
350 last
= (ybuf
[0] + (*src
++ << 1)) & 0x3F;
352 for (j
= 1; j
< avctx
->width
- 1; j
+= 2) {
353 cur
= (ybuf
[j
+ 1] + (*src
++ << 1)) & 0x3F;
354 ybuf
[j
] = (last
+ cur
) >> 1;
359 ybuf
+= avctx
->width
;
363 ybuf
= s
->pic
.data
[0];
364 for (j
= 0; j
< avctx
->height
; j
++) {
365 for (i
= 0; i
< avctx
->width
; i
++)
366 ybuf
[i
] = (src
[i
] << 2) | (src
[i
] >> 3);
368 ybuf
+= s
->pic
.linesize
[0];
374 static int xan_decode_frame(AVCodecContext
*avctx
,
375 void *data
, int *got_frame
,
378 XanContext
*s
= avctx
->priv_data
;
382 s
->pic
.reference
= 1;
383 s
->pic
.buffer_hints
= FF_BUFFER_HINTS_VALID
|
384 FF_BUFFER_HINTS_PRESERVE
|
385 FF_BUFFER_HINTS_REUSABLE
;
386 if ((ret
= avctx
->reget_buffer(avctx
, &s
->pic
))) {
387 av_log(s
->avctx
, AV_LOG_ERROR
, "reget_buffer() failed\n");
391 bytestream2_init(&s
->gb
, avpkt
->data
, avpkt
->size
);
392 ftype
= bytestream2_get_le32(&s
->gb
);
395 ret
= xan_decode_frame_type0(avctx
);
398 ret
= xan_decode_frame_type1(avctx
);
401 av_log(avctx
, AV_LOG_ERROR
, "Unknown frame type %d\n", ftype
);
402 return AVERROR_INVALIDDATA
;
408 *(AVFrame
*)data
= s
->pic
;
413 static av_cold
int xan_decode_end(AVCodecContext
*avctx
)
415 XanContext
*s
= avctx
->priv_data
;
418 avctx
->release_buffer(avctx
, &s
->pic
);
420 av_freep(&s
->y_buffer
);
421 av_freep(&s
->scratch_buffer
);
426 AVCodec ff_xan_wc4_decoder
= {
428 .type
= AVMEDIA_TYPE_VIDEO
,
429 .id
= AV_CODEC_ID_XAN_WC4
,
430 .priv_data_size
= sizeof(XanContext
),
431 .init
= xan_decode_init
,
432 .close
= xan_decode_end
,
433 .decode
= xan_decode_frame
,
434 .capabilities
= CODEC_CAP_DR1
,
435 .long_name
= NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),