Libav 0.7.1
libavcodec/xxan.c
Go to the documentation of this file.
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                 dest - orig_dest + size < back)
00134                 return -1;
00135             bytestream_get_buffer(&src, dest, size);
00136             dest += size;
00137             av_memcpy_backptr(dest, back, size2);
00138             dest += size2;
00139         } else {
00140             int finish = opcode >= 0xfc;
00141 
00142             size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
00143             if (src + size > src_end || dest + size > dest_end)
00144                 return -1;
00145             bytestream_get_buffer(&src, dest, size);
00146             dest += size;
00147             if (finish)
00148                 break;
00149         }
00150     }
00151     return dest - orig_dest;
00152 }
00153 
00154 static int xan_decode_chroma(AVCodecContext *avctx, AVPacket *avpkt)
00155 {
00156     const uint8_t *buf = avpkt->data;
00157     XanContext *s = avctx->priv_data;
00158     uint8_t *U, *V;
00159     unsigned chroma_off;
00160     int val, uval, vval;
00161     int i, j;
00162     const uint8_t *src, *src_end;
00163     const uint8_t *table;
00164     int mode, offset, dec_size;
00165 
00166     chroma_off = AV_RL32(buf + 4);
00167     if (!chroma_off)
00168         return 0;
00169     if (chroma_off + 10 >= avpkt->size) {
00170         av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n");
00171         return -1;
00172     }
00173     src    = avpkt->data + 4 + chroma_off;
00174     table  = src + 2;
00175     mode   = bytestream_get_le16(&src);
00176     offset = bytestream_get_le16(&src) * 2;
00177 
00178     if (src - avpkt->data >= avpkt->size - offset) {
00179         av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n");
00180         return -1;
00181     }
00182 
00183     memset(s->scratch_buffer, 0, s->buffer_size);
00184     dec_size = xan_unpack(s->scratch_buffer, s->buffer_size, src + offset,
00185                           avpkt->size - offset - (src - avpkt->data));
00186     if (dec_size < 0) {
00187         av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n");
00188         return -1;
00189     }
00190 
00191     U = s->pic.data[1];
00192     V = s->pic.data[2];
00193     src     = s->scratch_buffer;
00194     src_end = src + dec_size;
00195     if (mode) {
00196         for (j = 0; j < avctx->height >> 1; j++) {
00197             for (i = 0; i < avctx->width >> 1; i++) {
00198                 val = *src++;
00199                 if (val) {
00200                     val  = AV_RL16(table + (val << 1));
00201                     uval = (val >> 3) & 0xF8;
00202                     vval = (val >> 8) & 0xF8;
00203                     U[i] = uval | (uval >> 5);
00204                     V[i] = vval | (vval >> 5);
00205                 }
00206                 if (src == src_end)
00207                     return 0;
00208             }
00209             U += s->pic.linesize[1];
00210             V += s->pic.linesize[2];
00211         }
00212     } else {
00213         uint8_t *U2 = U + s->pic.linesize[1];
00214         uint8_t *V2 = V + s->pic.linesize[2];
00215 
00216         for (j = 0; j < avctx->height >> 2; j++) {
00217             for (i = 0; i < avctx->width >> 1; i += 2) {
00218                 val = *src++;
00219                 if (val) {
00220                     val  = AV_RL16(table + (val << 1));
00221                     uval = (val >> 3) & 0xF8;
00222                     vval = (val >> 8) & 0xF8;
00223                     U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5);
00224                     V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
00225                 }
00226             }
00227             U  += s->pic.linesize[1] * 2;
00228             V  += s->pic.linesize[2] * 2;
00229             U2 += s->pic.linesize[1] * 2;
00230             V2 += s->pic.linesize[2] * 2;
00231         }
00232     }
00233 
00234     return 0;
00235 }
00236 
00237 static int xan_decode_frame_type0(AVCodecContext *avctx, AVPacket *avpkt)
00238 {
00239     const uint8_t *buf = avpkt->data;
00240     XanContext *s = avctx->priv_data;
00241     uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer;
00242     unsigned  chroma_off, corr_off;
00243     int cur, last, size;
00244     int i, j;
00245     int ret;
00246 
00247     corr_off   = AV_RL32(buf + 8);
00248     chroma_off = AV_RL32(buf + 4);
00249 
00250     if ((ret = xan_decode_chroma(avctx, avpkt)) != 0)
00251         return ret;
00252 
00253     size = avpkt->size - 4;
00254     if (corr_off >= avpkt->size) {
00255         av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
00256         corr_off = 0;
00257     }
00258     if (corr_off)
00259         size = corr_off;
00260     if (chroma_off)
00261         size = FFMIN(size, chroma_off);
00262     ret = xan_unpack_luma(buf + 12, size, src, s->buffer_size >> 1);
00263     if (ret) {
00264         av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
00265         return ret;
00266     }
00267 
00268     ybuf = s->y_buffer;
00269     last = *src++;
00270     ybuf[0] = last << 1;
00271     for (j = 1; j < avctx->width - 1; j += 2) {
00272         cur = (last + *src++) & 0x1F;
00273         ybuf[j]   = last + cur;
00274         ybuf[j+1] = cur << 1;
00275         last = cur;
00276     }
00277     ybuf[j]  = last << 1;
00278     prev_buf = ybuf;
00279     ybuf += avctx->width;
00280 
00281     for (i = 1; i < avctx->height; i++) {
00282         last = ((prev_buf[0] >> 1) + *src++) & 0x1F;
00283         ybuf[0] = last << 1;
00284         for (j = 1; j < avctx->width - 1; j += 2) {
00285             cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F;
00286             ybuf[j]   = last + cur;
00287             ybuf[j+1] = cur << 1;
00288             last = cur;
00289         }
00290         ybuf[j] = last << 1;
00291         prev_buf = ybuf;
00292         ybuf += avctx->width;
00293     }
00294 
00295     if (corr_off) {
00296         int corr_end, dec_size;
00297 
00298         corr_end = avpkt->size;
00299         if (chroma_off > corr_off)
00300             corr_end = chroma_off;
00301         dec_size = xan_unpack(s->scratch_buffer, s->buffer_size,
00302                               avpkt->data + 8 + corr_off,
00303                               corr_end - corr_off);
00304         if (dec_size < 0)
00305             dec_size = 0;
00306         for (i = 0; i < dec_size; i++)
00307             s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
00308     }
00309 
00310     src  = s->y_buffer;
00311     ybuf = s->pic.data[0];
00312     for (j = 0; j < avctx->height; j++) {
00313         for (i = 0; i < avctx->width; i++)
00314             ybuf[i] = (src[i] << 2) | (src[i] >> 3);
00315         src  += avctx->width;
00316         ybuf += s->pic.linesize[0];
00317     }
00318 
00319     return 0;
00320 }
00321 
00322 static int xan_decode_frame_type1(AVCodecContext *avctx, AVPacket *avpkt)
00323 {
00324     const uint8_t *buf = avpkt->data;
00325     XanContext *s = avctx->priv_data;
00326     uint8_t *ybuf, *src = s->scratch_buffer;
00327     int cur, last;
00328     int i, j;
00329     int ret;
00330 
00331     if ((ret = xan_decode_chroma(avctx, avpkt)) != 0)
00332         return ret;
00333 
00334     ret = xan_unpack_luma(buf + 16, avpkt->size - 16, src,
00335                           s->buffer_size >> 1);
00336     if (ret) {
00337         av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
00338         return ret;
00339     }
00340 
00341     ybuf = s->y_buffer;
00342     for (i = 0; i < avctx->height; i++) {
00343         last = (ybuf[0] + (*src++ << 1)) & 0x3F;
00344         ybuf[0] = last;
00345         for (j = 1; j < avctx->width - 1; j += 2) {
00346             cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F;
00347             ybuf[j]   = (last + cur) >> 1;
00348             ybuf[j+1] = cur;
00349             last = cur;
00350         }
00351         ybuf[j] = last;
00352         ybuf += avctx->width;
00353     }
00354 
00355     src = s->y_buffer;
00356     ybuf = s->pic.data[0];
00357     for (j = 0; j < avctx->height; j++) {
00358         for (i = 0; i < avctx->width; i++)
00359             ybuf[i] = (src[i] << 2) | (src[i] >> 3);
00360         src  += avctx->width;
00361         ybuf += s->pic.linesize[0];
00362     }
00363 
00364     return 0;
00365 }
00366 
00367 static int xan_decode_frame(AVCodecContext *avctx,
00368                             void *data, int *data_size,
00369                             AVPacket *avpkt)
00370 {
00371     XanContext *s = avctx->priv_data;
00372     int ftype;
00373     int ret;
00374 
00375     s->pic.reference = 1;
00376     s->pic.buffer_hints = FF_BUFFER_HINTS_VALID |
00377                           FF_BUFFER_HINTS_PRESERVE |
00378                           FF_BUFFER_HINTS_REUSABLE;
00379     if ((ret = avctx->reget_buffer(avctx, &s->pic))) {
00380         av_log(s->avctx, AV_LOG_ERROR, "reget_buffer() failed\n");
00381         return ret;
00382     }
00383 
00384     ftype = AV_RL32(avpkt->data);
00385     switch (ftype) {
00386     case 0:
00387         ret = xan_decode_frame_type0(avctx, avpkt);
00388         break;
00389     case 1:
00390         ret = xan_decode_frame_type1(avctx, avpkt);
00391         break;
00392     default:
00393         av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype);
00394         return -1;
00395     }
00396     if (ret)
00397         return ret;
00398 
00399     *data_size = sizeof(AVFrame);
00400     *(AVFrame*)data = s->pic;
00401 
00402     return avpkt->size;
00403 }
00404 
00405 static av_cold int xan_decode_end(AVCodecContext *avctx)
00406 {
00407     XanContext *s = avctx->priv_data;
00408 
00409     if (s->pic.data[0])
00410         avctx->release_buffer(avctx, &s->pic);
00411 
00412     av_freep(&s->y_buffer);
00413     av_freep(&s->scratch_buffer);
00414 
00415     return 0;
00416 }
00417 
00418 AVCodec ff_xan_wc4_decoder = {
00419     "xan_wc4",
00420     AVMEDIA_TYPE_VIDEO,
00421     CODEC_ID_XAN_WC4,
00422     sizeof(XanContext),
00423     xan_decode_init,
00424     NULL,
00425     xan_decode_end,
00426     xan_decode_frame,
00427     CODEC_CAP_DR1,
00428     .long_name = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
00429 };
00430