Libav 0.7.1
|
00001 /* 00002 * Wing Commander/Xan Video Decoder 00003 * Copyright (C) 2011 Konstantin Shishkov 00004 * based on work by Mike Melanson 00005 * 00006 * This file is part of Libav. 00007 * 00008 * Libav is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * Libav is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with Libav; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 */ 00022 00023 #include "avcodec.h" 00024 #include "libavutil/intreadwrite.h" 00025 #include "bytestream.h" 00026 #define ALT_BITSTREAM_READER_LE 00027 #include "get_bits.h" 00028 // for av_memcpy_backptr 00029 #include "libavutil/lzo.h" 00030 00031 typedef struct XanContext { 00032 AVCodecContext *avctx; 00033 AVFrame pic; 00034 00035 uint8_t *y_buffer; 00036 uint8_t *scratch_buffer; 00037 int buffer_size; 00038 } XanContext; 00039 00040 static av_cold int xan_decode_init(AVCodecContext *avctx) 00041 { 00042 XanContext *s = avctx->priv_data; 00043 00044 s->avctx = avctx; 00045 00046 avctx->pix_fmt = PIX_FMT_YUV420P; 00047 00048 s->buffer_size = avctx->width * avctx->height; 00049 s->y_buffer = av_malloc(s->buffer_size); 00050 if (!s->y_buffer) 00051 return AVERROR(ENOMEM); 00052 s->scratch_buffer = av_malloc(s->buffer_size + 130); 00053 if (!s->scratch_buffer) { 00054 av_freep(&s->y_buffer); 00055 return AVERROR(ENOMEM); 00056 } 00057 00058 return 0; 00059 } 00060 00061 static int xan_unpack_luma(const uint8_t *src, const int src_size, 00062 uint8_t *dst, const int dst_size) 00063 { 00064 int tree_size, eof; 00065 const uint8_t *tree; 00066 int bits, mask; 00067 int tree_root, node; 00068 const uint8_t *dst_end = dst + dst_size; 00069 const uint8_t *src_end = src + src_size; 00070 00071 tree_size = *src++; 00072 eof = *src++; 00073 tree = src - eof * 2 - 2; 00074 tree_root = eof + tree_size; 00075 src += tree_size * 2; 00076 00077 node = tree_root; 00078 bits = *src++; 00079 mask = 0x80; 00080 for (;;) { 00081 int bit = !!(bits & mask); 00082 mask >>= 1; 00083 node = tree[node*2 + bit]; 00084 if (node == eof) 00085 break; 00086 if (node < eof) { 00087 *dst++ = node; 00088 if (dst > dst_end) 00089 break; 00090 node = tree_root; 00091 } 00092 if (!mask) { 00093 bits = *src++; 00094 if (src > src_end) 00095 break; 00096 mask = 0x80; 00097 } 00098 } 00099 return dst != dst_end; 00100 } 00101 00102 /* almost the same as in xan_wc3 decoder */ 00103 static int xan_unpack(uint8_t *dest, const int dest_len, 00104 const uint8_t *src, const int src_len) 00105 { 00106 uint8_t opcode; 00107 int size; 00108 uint8_t *orig_dest = dest; 00109 const uint8_t *src_end = src + src_len; 00110 const uint8_t *dest_end = dest + dest_len; 00111 00112 while (dest < dest_end) { 00113 opcode = *src++; 00114 00115 if (opcode < 0xe0) { 00116 int size2, back; 00117 if ((opcode & 0x80) == 0) { 00118 size = opcode & 3; 00119 back = ((opcode & 0x60) << 3) + *src++ + 1; 00120 size2 = ((opcode & 0x1c) >> 2) + 3; 00121 } else if ((opcode & 0x40) == 0) { 00122 size = *src >> 6; 00123 back = (bytestream_get_be16(&src) & 0x3fff) + 1; 00124 size2 = (opcode & 0x3f) + 4; 00125 } else { 00126 size = opcode & 3; 00127 back = ((opcode & 0x10) << 12) + bytestream_get_be16(&src) + 1; 00128 size2 = ((opcode & 0x0c) << 6) + *src++ + 5; 00129 if (size + size2 > dest_end - dest) 00130 break; 00131 } 00132 if (src + size > src_end || dest + size + size2 > dest_end) 00133 return -1; 00134 bytestream_get_buffer(&src, dest, size); 00135 dest += size; 00136 av_memcpy_backptr(dest, back, size2); 00137 dest += size2; 00138 } else { 00139 int finish = opcode >= 0xfc; 00140 00141 size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4; 00142 if (src + size > src_end || dest + size > dest_end) 00143 return -1; 00144 bytestream_get_buffer(&src, dest, size); 00145 dest += size; 00146 if (finish) 00147 break; 00148 } 00149 } 00150 return dest - orig_dest; 00151 } 00152 00153 static int xan_decode_chroma(AVCodecContext *avctx, AVPacket *avpkt) 00154 { 00155 const uint8_t *buf = avpkt->data; 00156 XanContext *s = avctx->priv_data; 00157 uint8_t *U, *V; 00158 unsigned chroma_off; 00159 int val, uval, vval; 00160 int i, j; 00161 const uint8_t *src, *src_end; 00162 const uint8_t *table; 00163 int mode, offset, dec_size; 00164 00165 chroma_off = AV_RL32(buf + 4); 00166 if (!chroma_off) 00167 return 0; 00168 if (chroma_off + 10 >= avpkt->size) { 00169 av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n"); 00170 return -1; 00171 } 00172 src = avpkt->data + 4 + chroma_off; 00173 table = src + 2; 00174 mode = bytestream_get_le16(&src); 00175 offset = bytestream_get_le16(&src) * 2; 00176 00177 if (src - avpkt->data >= avpkt->size - offset) { 00178 av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n"); 00179 return -1; 00180 } 00181 00182 memset(s->scratch_buffer, 0, s->buffer_size); 00183 dec_size = xan_unpack(s->scratch_buffer, s->buffer_size, src + offset, 00184 avpkt->size - offset - (src - avpkt->data)); 00185 if (dec_size < 0) { 00186 av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n"); 00187 return -1; 00188 } 00189 00190 U = s->pic.data[1]; 00191 V = s->pic.data[2]; 00192 src = s->scratch_buffer; 00193 src_end = src + dec_size; 00194 if (mode) { 00195 for (j = 0; j < avctx->height >> 1; j++) { 00196 for (i = 0; i < avctx->width >> 1; i++) { 00197 val = *src++; 00198 if (val) { 00199 val = AV_RL16(table + (val << 1)); 00200 uval = (val >> 3) & 0xF8; 00201 vval = (val >> 8) & 0xF8; 00202 U[i] = uval | (uval >> 5); 00203 V[i] = vval | (vval >> 5); 00204 } 00205 if (src == src_end) 00206 return 0; 00207 } 00208 U += s->pic.linesize[1]; 00209 V += s->pic.linesize[2]; 00210 } 00211 } else { 00212 uint8_t *U2 = U + s->pic.linesize[1]; 00213 uint8_t *V2 = V + s->pic.linesize[2]; 00214 00215 for (j = 0; j < avctx->height >> 2; j++) { 00216 for (i = 0; i < avctx->width >> 1; i += 2) { 00217 val = *src++; 00218 if (val) { 00219 val = AV_RL16(table + (val << 1)); 00220 uval = (val >> 3) & 0xF8; 00221 vval = (val >> 8) & 0xF8; 00222 U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5); 00223 V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5); 00224 } 00225 } 00226 U += s->pic.linesize[1] * 2; 00227 V += s->pic.linesize[2] * 2; 00228 U2 += s->pic.linesize[1] * 2; 00229 V2 += s->pic.linesize[2] * 2; 00230 } 00231 } 00232 00233 return 0; 00234 } 00235 00236 static int xan_decode_frame_type0(AVCodecContext *avctx, AVPacket *avpkt) 00237 { 00238 const uint8_t *buf = avpkt->data; 00239 XanContext *s = avctx->priv_data; 00240 uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer; 00241 unsigned chroma_off, corr_off; 00242 int cur, last, size; 00243 int i, j; 00244 int ret; 00245 00246 corr_off = AV_RL32(buf + 8); 00247 chroma_off = AV_RL32(buf + 4); 00248 00249 if ((ret = xan_decode_chroma(avctx, avpkt)) != 0) 00250 return ret; 00251 00252 size = avpkt->size - 4; 00253 if (corr_off >= avpkt->size) { 00254 av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n"); 00255 corr_off = 0; 00256 } 00257 if (corr_off) 00258 size = corr_off; 00259 if (chroma_off) 00260 size = FFMIN(size, chroma_off); 00261 ret = xan_unpack_luma(buf + 12, size, src, s->buffer_size >> 1); 00262 if (ret) { 00263 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n"); 00264 return ret; 00265 } 00266 00267 ybuf = s->y_buffer; 00268 last = *src++; 00269 ybuf[0] = last << 1; 00270 for (j = 1; j < avctx->width - 1; j += 2) { 00271 cur = (last + *src++) & 0x1F; 00272 ybuf[j] = last + cur; 00273 ybuf[j+1] = cur << 1; 00274 last = cur; 00275 } 00276 ybuf[j] = last << 1; 00277 prev_buf = ybuf; 00278 ybuf += avctx->width; 00279 00280 for (i = 1; i < avctx->height; i++) { 00281 last = ((prev_buf[0] >> 1) + *src++) & 0x1F; 00282 ybuf[0] = last << 1; 00283 for (j = 1; j < avctx->width - 1; j += 2) { 00284 cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F; 00285 ybuf[j] = last + cur; 00286 ybuf[j+1] = cur << 1; 00287 last = cur; 00288 } 00289 ybuf[j] = last << 1; 00290 prev_buf = ybuf; 00291 ybuf += avctx->width; 00292 } 00293 00294 if (corr_off) { 00295 int corr_end, dec_size; 00296 00297 corr_end = avpkt->size; 00298 if (chroma_off > corr_off) 00299 corr_end = chroma_off; 00300 dec_size = xan_unpack(s->scratch_buffer, s->buffer_size, 00301 avpkt->data + 8 + corr_off, 00302 corr_end - corr_off); 00303 if (dec_size < 0) 00304 dec_size = 0; 00305 for (i = 0; i < dec_size; i++) 00306 s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F; 00307 } 00308 00309 src = s->y_buffer; 00310 ybuf = s->pic.data[0]; 00311 for (j = 0; j < avctx->height; j++) { 00312 for (i = 0; i < avctx->width; i++) 00313 ybuf[i] = (src[i] << 2) | (src[i] >> 3); 00314 src += avctx->width; 00315 ybuf += s->pic.linesize[0]; 00316 } 00317 00318 return 0; 00319 } 00320 00321 static int xan_decode_frame_type1(AVCodecContext *avctx, AVPacket *avpkt) 00322 { 00323 const uint8_t *buf = avpkt->data; 00324 XanContext *s = avctx->priv_data; 00325 uint8_t *ybuf, *src = s->scratch_buffer; 00326 int cur, last; 00327 int i, j; 00328 int ret; 00329 00330 if ((ret = xan_decode_chroma(avctx, avpkt)) != 0) 00331 return ret; 00332 00333 ret = xan_unpack_luma(buf + 16, avpkt->size - 16, src, 00334 s->buffer_size >> 1); 00335 if (ret) { 00336 av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n"); 00337 return ret; 00338 } 00339 00340 ybuf = s->y_buffer; 00341 for (i = 0; i < avctx->height; i++) { 00342 last = (ybuf[0] + (*src++ << 1)) & 0x3F; 00343 ybuf[0] = last; 00344 for (j = 1; j < avctx->width - 1; j += 2) { 00345 cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F; 00346 ybuf[j] = (last + cur) >> 1; 00347 ybuf[j+1] = cur; 00348 last = cur; 00349 } 00350 ybuf[j] = last; 00351 ybuf += avctx->width; 00352 } 00353 00354 src = s->y_buffer; 00355 ybuf = s->pic.data[0]; 00356 for (j = 0; j < avctx->height; j++) { 00357 for (i = 0; i < avctx->width; i++) 00358 ybuf[i] = (src[i] << 2) | (src[i] >> 3); 00359 src += avctx->width; 00360 ybuf += s->pic.linesize[0]; 00361 } 00362 00363 return 0; 00364 } 00365 00366 static int xan_decode_frame(AVCodecContext *avctx, 00367 void *data, int *data_size, 00368 AVPacket *avpkt) 00369 { 00370 XanContext *s = avctx->priv_data; 00371 int ftype; 00372 int ret; 00373 00374 s->pic.reference = 1; 00375 s->pic.buffer_hints = FF_BUFFER_HINTS_VALID | 00376 FF_BUFFER_HINTS_PRESERVE | 00377 FF_BUFFER_HINTS_REUSABLE; 00378 if ((ret = avctx->reget_buffer(avctx, &s->pic))) { 00379 av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); 00380 return ret; 00381 } 00382 00383 ftype = AV_RL32(avpkt->data); 00384 switch (ftype) { 00385 case 0: 00386 ret = xan_decode_frame_type0(avctx, avpkt); 00387 break; 00388 case 1: 00389 ret = xan_decode_frame_type1(avctx, avpkt); 00390 break; 00391 default: 00392 av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype); 00393 return -1; 00394 } 00395 if (ret) 00396 return ret; 00397 00398 *data_size = sizeof(AVFrame); 00399 *(AVFrame*)data = s->pic; 00400 00401 return avpkt->size; 00402 } 00403 00404 static av_cold int xan_decode_end(AVCodecContext *avctx) 00405 { 00406 XanContext *s = avctx->priv_data; 00407 00408 if (s->pic.data[0]) 00409 avctx->release_buffer(avctx, &s->pic); 00410 00411 av_freep(&s->y_buffer); 00412 av_freep(&s->scratch_buffer); 00413 00414 return 0; 00415 } 00416 00417 AVCodec ff_xan_wc4_decoder = { 00418 "xan_wc4", 00419 AVMEDIA_TYPE_VIDEO, 00420 CODEC_ID_XAN_WC4, 00421 sizeof(XanContext), 00422 xan_decode_init, 00423 NULL, 00424 xan_decode_end, 00425 xan_decode_frame, 00426 CODEC_CAP_DR1, 00427 .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"), 00428 }; 00429