• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

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

Generated on Wed Apr 11 2012 07:31:35 for FFmpeg by  doxygen 1.7.1