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 31typedef struct XanContext { 32 AVCodecContext *avctx; 33 AVFrame *pic; 34 35 uint8_t *y_buffer; 36 uint8_t *scratch_buffer; 37 int buffer_size; 38 GetByteContext gb; 39} XanContext; 40 41static av_cold int xan_decode_end(AVCodecContext *avctx) 42{ 43 XanContext *s = avctx->priv_data; 44 45 av_frame_free(&s->pic); 46 47 av_freep(&s->y_buffer); 48 av_freep(&s->scratch_buffer); 49 50 return 0; 51} 52 53static av_cold int xan_decode_init(AVCodecContext *avctx) 54{ 55 XanContext *s = avctx->priv_data; 56 57 s->avctx = avctx; 58 59 avctx->pix_fmt = AV_PIX_FMT_YUV420P; 60 61 if (avctx->height < 8) { 62 av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height); 63 return AVERROR(EINVAL); 64 } 65 if (avctx->width & 1) { 66 av_log(avctx, AV_LOG_ERROR, "Invalid frame width: %d.\n", avctx->width); 67 return AVERROR(EINVAL); 68 } 69 70 s->buffer_size = avctx->width * avctx->height; 71 s->y_buffer = av_malloc(s->buffer_size); 72 if (!s->y_buffer) 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); 78 } 79 80 s->pic = av_frame_alloc(); 81 if (!s->pic) { 82 xan_decode_end(avctx); 83 return AVERROR(ENOMEM); 84 } 85 86 return 0; 87} 88 89static int xan_unpack_luma(XanContext *s, 90 uint8_t *dst, const int dst_size) 91{ 92 int tree_size, eof; 93 int bits, mask; 94 int tree_root, node; 95 const uint8_t *dst_end = dst + dst_size; 96 GetByteContext tree = s->gb; 97 int start_off = bytestream2_tell(&tree); 98 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); 103 104 node = tree_root; 105 bits = bytestream2_get_byte(&s->gb); 106 mask = 0x80; 107 for (;;) { 108 int bit = !!(bits & mask); 109 mask >>= 1; 110 bytestream2_seek(&tree, start_off + node*2 + bit - eof * 2, SEEK_SET); 111 node = bytestream2_get_byte(&tree); 112 if (node == eof) 113 break; 114 if (node < eof) { 115 *dst++ = node; 116 if (dst > dst_end) 117 break; 118 node = tree_root; 119 } 120 if (!mask) { 121 if (bytestream2_get_bytes_left(&s->gb) <= 0) 122 break; 123 bits = bytestream2_get_byteu(&s->gb); 124 mask = 0x80; 125 } 126 } 127 return dst != dst_end ? AVERROR_INVALIDDATA : 0; 128} 129 130/* almost the same as in xan_wc3 decoder */ 131static int xan_unpack(XanContext *s, 132 uint8_t *dest, const int dest_len) 133{ 134 uint8_t opcode; 135 int size; 136 uint8_t *orig_dest = dest; 137 const uint8_t *dest_end = dest + dest_len; 138 139 while (dest < dest_end) { 140 if (bytestream2_get_bytes_left(&s->gb) <= 0) 141 return AVERROR_INVALIDDATA; 142 143 opcode = bytestream2_get_byteu(&s->gb); 144 145 if (opcode < 0xe0) { 146 int size2, back; 147 if ((opcode & 0x80) == 0) { 148 size = opcode & 3; 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; 155 } else { 156 size = opcode & 3; 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) 160 break; 161 } 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); 166 dest += size; 167 av_memcpy_backptr(dest, back, size2); 168 dest += size2; 169 } else { 170 int finish = opcode >= 0xfc; 171 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); 176 dest += size; 177 if (finish) 178 break; 179 } 180 } 181 return dest - orig_dest; 182} 183 184static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off) 185{ 186 XanContext *s = avctx->priv_data; 187 uint8_t *U, *V; 188 int val, uval, vval; 189 int i, j; 190 const uint8_t *src, *src_end; 191 const uint8_t *table; 192 int mode, offset, dec_size, table_size; 193 194 if (!chroma_off) 195 return 0; 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; 199 } 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; 205 table_size += 1; 206 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; 210 } 211 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); 215 if (dec_size < 0) { 216 av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n"); 217 return dec_size; 218 } 219 220 U = s->pic->data[1]; 221 V = s->pic->data[2]; 222 src = s->scratch_buffer; 223 src_end = src + dec_size; 224 if (mode) { 225 for (j = 0; j < avctx->height >> 1; j++) { 226 for (i = 0; i < avctx->width >> 1; i++) { 227 if (src_end - src < 1) 228 return 0; 229 val = *src++; 230 if (val) { 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); 238 } 239 } 240 U += s->pic->linesize[1]; 241 V += s->pic->linesize[2]; 242 } 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); 246 } 247 } else { 248 uint8_t *U2 = U + s->pic->linesize[1]; 249 uint8_t *V2 = V + s->pic->linesize[2]; 250 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) 254 return 0; 255 val = *src++; 256 if (val) { 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); 264 } 265 } 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; 270 } 271 if (avctx->height & 3) { 272 int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2; 273 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]); 276 } 277 } 278 279 return 0; 280} 281 282static int xan_decode_frame_type0(AVCodecContext *avctx) 283{ 284 XanContext *s = avctx->priv_data; 285 uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer; 286 unsigned chroma_off, corr_off; 287 int cur, last; 288 int i, j; 289 int ret; 290 291 chroma_off = bytestream2_get_le32(&s->gb); 292 corr_off = bytestream2_get_le32(&s->gb); 293 294 if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0) 295 return ret; 296 297 if (corr_off >= bytestream2_size(&s->gb)) { 298 av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n"); 299 corr_off = 0; 300 } 301 bytestream2_seek(&s->gb, 12, SEEK_SET); 302 ret = xan_unpack_luma(s, src, s->buffer_size >> 1); 303 if (ret) { 304 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n"); 305 return ret; 306 } 307 308 ybuf = s->y_buffer; 309 last = *src++; 310 ybuf[0] = last << 1; 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; 315 last = cur; 316 } 317 ybuf[j] = last << 1; 318 prev_buf = ybuf; 319 ybuf += avctx->width; 320 321 for (i = 1; i < avctx->height; i++) { 322 last = ((prev_buf[0] >> 1) + *src++) & 0x1F; 323 ybuf[0] = last << 1; 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; 328 last = cur; 329 } 330 ybuf[j] = last << 1; 331 prev_buf = ybuf; 332 ybuf += avctx->width; 333 } 334 335 if (corr_off) { 336 int dec_size; 337 338 bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET); 339 dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2); 340 if (dec_size < 0) 341 dec_size = 0; 342 else 343 dec_size = FFMIN(dec_size, s->buffer_size/2 - 1); 344 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; 347 } 348 349 src = s->y_buffer; 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); 354 src += avctx->width; 355 ybuf += s->pic->linesize[0]; 356 } 357 358 return 0; 359} 360 361static int xan_decode_frame_type1(AVCodecContext *avctx) 362{ 363 XanContext *s = avctx->priv_data; 364 uint8_t *ybuf, *src = s->scratch_buffer; 365 int cur, last; 366 int i, j; 367 int ret; 368 369 if ((ret = xan_decode_chroma(avctx, bytestream2_get_le32(&s->gb))) != 0) 370 return ret; 371 372 bytestream2_seek(&s->gb, 16, SEEK_SET); 373 ret = xan_unpack_luma(s, src, 374 s->buffer_size >> 1); 375 if (ret) { 376 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n"); 377 return ret; 378 } 379 380 ybuf = s->y_buffer; 381 for (i = 0; i < avctx->height; i++) { 382 last = (ybuf[0] + (*src++ << 1)) & 0x3F; 383 ybuf[0] = last; 384 for (j = 1; j < avctx->width - 1; j += 2) { 385 cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F; 386 ybuf[j] = (last + cur) >> 1; 387 ybuf[j+1] = cur; 388 last = cur; 389 } 390 ybuf[j] = last; 391 ybuf += avctx->width; 392 } 393 394 src = s->y_buffer; 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); 399 src += avctx->width; 400 ybuf += s->pic->linesize[0]; 401 } 402 403 return 0; 404} 405 406static int xan_decode_frame(AVCodecContext *avctx, 407 void *data, int *got_frame, 408 AVPacket *avpkt) 409{ 410 XanContext *s = avctx->priv_data; 411 int ftype; 412 int ret; 413 414 if ((ret = ff_reget_buffer(avctx, s->pic)) < 0) 415 return ret; 416 417 bytestream2_init(&s->gb, avpkt->data, avpkt->size); 418 ftype = bytestream2_get_le32(&s->gb); 419 switch (ftype) { 420 case 0: 421 ret = xan_decode_frame_type0(avctx); 422 break; 423 case 1: 424 ret = xan_decode_frame_type1(avctx); 425 break; 426 default: 427 av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype); 428 return AVERROR_INVALIDDATA; 429 } 430 if (ret) 431 return ret; 432 433 if ((ret = av_frame_ref(data, s->pic)) < 0) 434 return ret; 435 436 *got_frame = 1; 437 438 return avpkt->size; 439} 440 441AVCodec ff_xan_wc4_decoder = { 442 .name = "xan_wc4", 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, 451}; 452