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                 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