LCOV - code coverage report
Current view: top level - libavcodec - xxan.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 228 269 84.8 %
Date: 2017-12-17 04:34:43 Functions: 8 8 100.0 %

          Line data    Source code
       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 "libavutil/intreadwrite.h"
      24             : #include "libavutil/mem.h"
      25             : 
      26             : #include "avcodec.h"
      27             : #include "bytestream.h"
      28             : #include "internal.h"
      29             : 
      30             : typedef struct XanContext {
      31             :     AVCodecContext *avctx;
      32             :     AVFrame *pic;
      33             : 
      34             :     uint8_t *y_buffer;
      35             :     uint8_t *scratch_buffer;
      36             :     int     buffer_size;
      37             :     GetByteContext gb;
      38             : } XanContext;
      39             : 
      40           3 : static av_cold int xan_decode_end(AVCodecContext *avctx)
      41             : {
      42           3 :     XanContext *s = avctx->priv_data;
      43             : 
      44           3 :     av_frame_free(&s->pic);
      45             : 
      46           3 :     av_freep(&s->y_buffer);
      47           3 :     av_freep(&s->scratch_buffer);
      48             : 
      49           3 :     return 0;
      50             : }
      51             : 
      52           3 : static av_cold int xan_decode_init(AVCodecContext *avctx)
      53             : {
      54           3 :     XanContext *s = avctx->priv_data;
      55             : 
      56           3 :     s->avctx = avctx;
      57             : 
      58           3 :     avctx->pix_fmt = AV_PIX_FMT_YUV420P;
      59             : 
      60           3 :     if (avctx->height < 8) {
      61           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid frame height: %d.\n", avctx->height);
      62           0 :         return AVERROR(EINVAL);
      63             :     }
      64           3 :     if (avctx->width & 1) {
      65           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid frame width: %d.\n", avctx->width);
      66           0 :         return AVERROR(EINVAL);
      67             :     }
      68             : 
      69           3 :     s->buffer_size = avctx->width * avctx->height;
      70           3 :     s->y_buffer = av_malloc(s->buffer_size);
      71           3 :     if (!s->y_buffer)
      72           0 :         return AVERROR(ENOMEM);
      73           3 :     s->scratch_buffer = av_malloc(s->buffer_size + 130);
      74           3 :     if (!s->scratch_buffer) {
      75           0 :         xan_decode_end(avctx);
      76           0 :         return AVERROR(ENOMEM);
      77             :     }
      78             : 
      79           3 :     s->pic = av_frame_alloc();
      80           3 :     if (!s->pic) {
      81           0 :         xan_decode_end(avctx);
      82           0 :         return AVERROR(ENOMEM);
      83             :     }
      84             : 
      85           3 :     return 0;
      86             : }
      87             : 
      88          21 : static int xan_unpack_luma(XanContext *s,
      89             :                            uint8_t *dst, const int dst_size)
      90             : {
      91             :     int tree_size, eof;
      92             :     int bits, mask;
      93             :     int tree_root, node;
      94          21 :     const uint8_t *dst_end = dst + dst_size;
      95          21 :     GetByteContext tree = s->gb;
      96          21 :     int start_off = bytestream2_tell(&tree);
      97             : 
      98          21 :     tree_size = bytestream2_get_byte(&s->gb);
      99          21 :     eof       = bytestream2_get_byte(&s->gb);
     100          21 :     tree_root = eof + tree_size;
     101          21 :     bytestream2_skip(&s->gb, tree_size * 2);
     102             : 
     103          21 :     node = tree_root;
     104          21 :     bits = bytestream2_get_byte(&s->gb);
     105          21 :     mask = 0x80;
     106      691350 :     for (;;) {
     107      691371 :         int bit = !!(bits & mask);
     108      691371 :         mask >>= 1;
     109      691371 :         bytestream2_seek(&tree, start_off + node*2 + bit - eof * 2, SEEK_SET);
     110      691371 :         node = bytestream2_get_byte(&tree);
     111      691371 :         if (node == eof)
     112          21 :             break;
     113      691350 :         if (node < eof) {
     114      554400 :             *dst++ = node;
     115      554400 :             if (dst > dst_end)
     116           0 :                 break;
     117      554400 :             node = tree_root;
     118             :         }
     119      691350 :         if (!mask) {
     120       86409 :             if (bytestream2_get_bytes_left(&s->gb) <= 0)
     121           0 :                 break;
     122       86409 :             bits = bytestream2_get_byteu(&s->gb);
     123       86409 :             mask = 0x80;
     124             :         }
     125             :     }
     126          21 :     return dst != dst_end ? AVERROR_INVALIDDATA : 0;
     127             : }
     128             : 
     129             : /* almost the same as in xan_wc3 decoder */
     130          26 : static int xan_unpack(XanContext *s,
     131             :                       uint8_t *dest, const int dest_len)
     132             : {
     133             :     uint8_t opcode;
     134             :     int size;
     135          26 :     uint8_t *orig_dest = dest;
     136          26 :     const uint8_t *dest_end = dest + dest_len;
     137             : 
     138       11887 :     while (dest < dest_end) {
     139       11856 :         if (bytestream2_get_bytes_left(&s->gb) <= 0)
     140           0 :             return AVERROR_INVALIDDATA;
     141             : 
     142       11856 :         opcode = bytestream2_get_byteu(&s->gb);
     143             : 
     144       11856 :         if (opcode < 0xe0) {
     145             :             int size2, back;
     146       11348 :             if ((opcode & 0x80) == 0) {
     147        7882 :                 size  = opcode & 3;
     148        7882 :                 back  = ((opcode & 0x60) << 3) + bytestream2_get_byte(&s->gb) + 1;
     149        7882 :                 size2 = ((opcode & 0x1c) >> 2) + 3;
     150        3466 :             } else if ((opcode & 0x40) == 0) {
     151        3066 :                 size  = bytestream2_peek_byte(&s->gb) >> 6;
     152        3066 :                 back  = (bytestream2_get_be16(&s->gb) & 0x3fff) + 1;
     153        3066 :                 size2 = (opcode & 0x3f) + 4;
     154             :             } else {
     155         400 :                 size  = opcode & 3;
     156         400 :                 back  = ((opcode & 0x10) << 12) + bytestream2_get_be16(&s->gb) + 1;
     157         400 :                 size2 = ((opcode & 0x0c) <<  6) + bytestream2_get_byte(&s->gb) + 5;
     158         400 :                 if (size + size2 > dest_end - dest)
     159           0 :                     break;
     160             :             }
     161       22696 :             if (dest + size + size2 > dest_end ||
     162       11348 :                 dest - orig_dest + size < back)
     163           0 :                 return AVERROR_INVALIDDATA;
     164       11348 :             bytestream2_get_buffer(&s->gb, dest, size);
     165       11348 :             dest += size;
     166       11348 :             av_memcpy_backptr(dest, back, size2);
     167       11348 :             dest += size2;
     168             :         } else {
     169         508 :             int finish = opcode >= 0xfc;
     170             : 
     171         508 :             size = finish ? opcode & 3 : ((opcode & 0x1f) << 2) + 4;
     172         508 :             if (dest_end - dest < size)
     173           0 :                 return AVERROR_INVALIDDATA;
     174         508 :             bytestream2_get_buffer(&s->gb, dest, size);
     175         508 :             dest += size;
     176         508 :             if (finish)
     177          21 :                 break;
     178             :         }
     179             :     }
     180          26 :     return dest - orig_dest;
     181             : }
     182             : 
     183          21 : static int xan_decode_chroma(AVCodecContext *avctx, unsigned chroma_off)
     184             : {
     185          21 :     XanContext *s = avctx->priv_data;
     186             :     uint8_t *U, *V;
     187             :     int val, uval, vval;
     188             :     int i, j;
     189             :     const uint8_t *src, *src_end;
     190             :     const uint8_t *table;
     191             :     int mode, offset, dec_size, table_size;
     192             : 
     193          21 :     if (!chroma_off)
     194           0 :         return 0;
     195          21 :     if (chroma_off + 4 >= bytestream2_get_bytes_left(&s->gb)) {
     196           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid chroma block position\n");
     197           0 :         return AVERROR_INVALIDDATA;
     198             :     }
     199          21 :     bytestream2_seek(&s->gb, chroma_off + 4, SEEK_SET);
     200          21 :     mode        = bytestream2_get_le16(&s->gb);
     201          21 :     table       = s->gb.buffer;
     202          21 :     table_size  = bytestream2_get_le16(&s->gb);
     203          21 :     offset      = table_size * 2;
     204          21 :     table_size += 1;
     205             : 
     206          21 :     if (offset >= bytestream2_get_bytes_left(&s->gb)) {
     207           0 :         av_log(avctx, AV_LOG_ERROR, "Invalid chroma block offset\n");
     208           0 :         return AVERROR_INVALIDDATA;
     209             :     }
     210             : 
     211          21 :     bytestream2_skip(&s->gb, offset);
     212          21 :     memset(s->scratch_buffer, 0, s->buffer_size);
     213          21 :     dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size);
     214          21 :     if (dec_size < 0) {
     215           0 :         av_log(avctx, AV_LOG_ERROR, "Chroma unpacking failed\n");
     216           0 :         return dec_size;
     217             :     }
     218             : 
     219          21 :     U = s->pic->data[1];
     220          21 :     V = s->pic->data[2];
     221          21 :     src     = s->scratch_buffer;
     222          21 :     src_end = src + dec_size;
     223          21 :     if (mode) {
     224         332 :         for (j = 0; j < avctx->height >> 1; j++) {
     225       52808 :             for (i = 0; i < avctx->width >> 1; i++) {
     226       52480 :                 if (src_end - src < 1)
     227           0 :                     return 0;
     228       52480 :                 val = *src++;
     229       52480 :                 if (val) {
     230       52480 :                     if (val >= table_size)
     231           0 :                         return AVERROR_INVALIDDATA;
     232       52480 :                     val  = AV_RL16(table + (val << 1));
     233       52480 :                     uval = (val >> 3) & 0xF8;
     234       52480 :                     vval = (val >> 8) & 0xF8;
     235       52480 :                     U[i] = uval | (uval >> 5);
     236       52480 :                     V[i] = vval | (vval >> 5);
     237             :                 }
     238             :             }
     239         328 :             U += s->pic->linesize[1];
     240         328 :             V += s->pic->linesize[2];
     241             :         }
     242           4 :         if (avctx->height & 1) {
     243           4 :             memcpy(U, U - s->pic->linesize[1], avctx->width >> 1);
     244           4 :             memcpy(V, V - s->pic->linesize[2], avctx->width >> 1);
     245             :         }
     246             :     } else {
     247          17 :         uint8_t *U2 = U + s->pic->linesize[1];
     248          17 :         uint8_t *V2 = V + s->pic->linesize[2];
     249             : 
     250         714 :         for (j = 0; j < avctx->height >> 2; j++) {
     251       56457 :             for (i = 0; i < avctx->width >> 1; i += 2) {
     252       55760 :                 if (src_end - src < 1)
     253           0 :                     return 0;
     254       55760 :                 val = *src++;
     255       55760 :                 if (val) {
     256       17613 :                     if (val >= table_size)
     257           0 :                         return AVERROR_INVALIDDATA;
     258       17613 :                     val  = AV_RL16(table + (val << 1));
     259       17613 :                     uval = (val >> 3) & 0xF8;
     260       17613 :                     vval = (val >> 8) & 0xF8;
     261       17613 :                     U[i] = U[i+1] = U2[i] = U2[i+1] = uval | (uval >> 5);
     262       17613 :                     V[i] = V[i+1] = V2[i] = V2[i+1] = vval | (vval >> 5);
     263             :                 }
     264             :             }
     265         697 :             U  += s->pic->linesize[1] * 2;
     266         697 :             V  += s->pic->linesize[2] * 2;
     267         697 :             U2 += s->pic->linesize[1] * 2;
     268         697 :             V2 += s->pic->linesize[2] * 2;
     269             :         }
     270          17 :         if (avctx->height & 3) {
     271          17 :             int lines = ((avctx->height + 1) >> 1) - (avctx->height >> 2) * 2;
     272             : 
     273          17 :             memcpy(U, U - lines * s->pic->linesize[1], lines * s->pic->linesize[1]);
     274          17 :             memcpy(V, V - lines * s->pic->linesize[2], lines * s->pic->linesize[2]);
     275             :         }
     276             :     }
     277             : 
     278          21 :     return 0;
     279             : }
     280             : 
     281           5 : static int xan_decode_frame_type0(AVCodecContext *avctx)
     282             : {
     283           5 :     XanContext *s = avctx->priv_data;
     284           5 :     uint8_t *ybuf, *prev_buf, *src = s->scratch_buffer;
     285             :     unsigned  chroma_off, corr_off;
     286             :     int cur, last;
     287             :     int i, j;
     288             :     int ret;
     289             : 
     290           5 :     chroma_off = bytestream2_get_le32(&s->gb);
     291           5 :     corr_off   = bytestream2_get_le32(&s->gb);
     292             : 
     293           5 :     if ((ret = xan_decode_chroma(avctx, chroma_off)) != 0)
     294           0 :         return ret;
     295             : 
     296           5 :     if (corr_off >= bytestream2_size(&s->gb)) {
     297           0 :         av_log(avctx, AV_LOG_WARNING, "Ignoring invalid correction block position\n");
     298           0 :         corr_off = 0;
     299             :     }
     300           5 :     bytestream2_seek(&s->gb, 12, SEEK_SET);
     301           5 :     ret = xan_unpack_luma(s, src, s->buffer_size >> 1);
     302           5 :     if (ret) {
     303           0 :         av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
     304           0 :         return ret;
     305             :     }
     306             : 
     307           5 :     ybuf = s->y_buffer;
     308           5 :     last = *src++;
     309           5 :     ybuf[0] = last << 1;
     310         800 :     for (j = 1; j < avctx->width - 1; j += 2) {
     311         795 :         cur = (last + *src++) & 0x1F;
     312         795 :         ybuf[j]   = last + cur;
     313         795 :         ybuf[j+1] = cur << 1;
     314         795 :         last = cur;
     315             :     }
     316           5 :     ybuf[j]  = last << 1;
     317           5 :     prev_buf = ybuf;
     318           5 :     ybuf += avctx->width;
     319             : 
     320         825 :     for (i = 1; i < avctx->height; i++) {
     321         820 :         last = ((prev_buf[0] >> 1) + *src++) & 0x1F;
     322         820 :         ybuf[0] = last << 1;
     323      131200 :         for (j = 1; j < avctx->width - 1; j += 2) {
     324      130380 :             cur = ((prev_buf[j + 1] >> 1) + *src++) & 0x1F;
     325      130380 :             ybuf[j]   = last + cur;
     326      130380 :             ybuf[j+1] = cur << 1;
     327      130380 :             last = cur;
     328             :         }
     329         820 :         ybuf[j] = last << 1;
     330         820 :         prev_buf = ybuf;
     331         820 :         ybuf += avctx->width;
     332             :     }
     333             : 
     334           5 :     if (corr_off) {
     335             :         int dec_size;
     336             : 
     337           5 :         bytestream2_seek(&s->gb, 8 + corr_off, SEEK_SET);
     338           5 :         dec_size = xan_unpack(s, s->scratch_buffer, s->buffer_size / 2);
     339           5 :         if (dec_size < 0)
     340           0 :             dec_size = 0;
     341             :         else
     342           5 :             dec_size = FFMIN(dec_size, s->buffer_size/2 - 1);
     343             : 
     344      132000 :         for (i = 0; i < dec_size; i++)
     345      131995 :             s->y_buffer[i*2+1] = (s->y_buffer[i*2+1] + (s->scratch_buffer[i] << 1)) & 0x3F;
     346             :     }
     347             : 
     348           5 :     src  = s->y_buffer;
     349           5 :     ybuf = s->pic->data[0];
     350         830 :     for (j = 0; j < avctx->height; j++) {
     351      264825 :         for (i = 0; i < avctx->width; i++)
     352      264000 :             ybuf[i] = (src[i] << 2) | (src[i] >> 3);
     353         825 :         src  += avctx->width;
     354         825 :         ybuf += s->pic->linesize[0];
     355             :     }
     356             : 
     357           5 :     return 0;
     358             : }
     359             : 
     360          16 : static int xan_decode_frame_type1(AVCodecContext *avctx)
     361             : {
     362          16 :     XanContext *s = avctx->priv_data;
     363          16 :     uint8_t *ybuf, *src = s->scratch_buffer;
     364             :     int cur, last;
     365             :     int i, j;
     366             :     int ret;
     367             : 
     368          16 :     if ((ret = xan_decode_chroma(avctx, bytestream2_get_le32(&s->gb))) != 0)
     369           0 :         return ret;
     370             : 
     371          16 :     bytestream2_seek(&s->gb, 16, SEEK_SET);
     372          16 :     ret = xan_unpack_luma(s, src,
     373          16 :                           s->buffer_size >> 1);
     374          16 :     if (ret) {
     375           0 :         av_log(avctx, AV_LOG_ERROR, "Luma decoding failed\n");
     376           0 :         return ret;
     377             :     }
     378             : 
     379          16 :     ybuf = s->y_buffer;
     380        2656 :     for (i = 0; i < avctx->height; i++) {
     381        2640 :         last = (ybuf[0] + (*src++ << 1)) & 0x3F;
     382        2640 :         ybuf[0] = last;
     383      422400 :         for (j = 1; j < avctx->width - 1; j += 2) {
     384      419760 :             cur = (ybuf[j + 1] + (*src++ << 1)) & 0x3F;
     385      419760 :             ybuf[j]   = (last + cur) >> 1;
     386      419760 :             ybuf[j+1] = cur;
     387      419760 :             last = cur;
     388             :         }
     389        2640 :         ybuf[j] = last;
     390        2640 :         ybuf += avctx->width;
     391             :     }
     392             : 
     393          16 :     src = s->y_buffer;
     394          16 :     ybuf = s->pic->data[0];
     395        2656 :     for (j = 0; j < avctx->height; j++) {
     396      847440 :         for (i = 0; i < avctx->width; i++)
     397      844800 :             ybuf[i] = (src[i] << 2) | (src[i] >> 3);
     398        2640 :         src  += avctx->width;
     399        2640 :         ybuf += s->pic->linesize[0];
     400             :     }
     401             : 
     402          16 :     return 0;
     403             : }
     404             : 
     405          21 : static int xan_decode_frame(AVCodecContext *avctx,
     406             :                             void *data, int *got_frame,
     407             :                             AVPacket *avpkt)
     408             : {
     409          21 :     XanContext *s = avctx->priv_data;
     410             :     int ftype;
     411             :     int ret;
     412             : 
     413          21 :     if ((ret = ff_reget_buffer(avctx, s->pic)) < 0)
     414           0 :         return ret;
     415             : 
     416          21 :     bytestream2_init(&s->gb, avpkt->data, avpkt->size);
     417          21 :     ftype = bytestream2_get_le32(&s->gb);
     418          21 :     switch (ftype) {
     419           5 :     case 0:
     420           5 :         ret = xan_decode_frame_type0(avctx);
     421           5 :         break;
     422          16 :     case 1:
     423          16 :         ret = xan_decode_frame_type1(avctx);
     424          16 :         break;
     425           0 :     default:
     426           0 :         av_log(avctx, AV_LOG_ERROR, "Unknown frame type %d\n", ftype);
     427           0 :         return AVERROR_INVALIDDATA;
     428             :     }
     429          21 :     if (ret)
     430           0 :         return ret;
     431             : 
     432          21 :     if ((ret = av_frame_ref(data, s->pic)) < 0)
     433           0 :         return ret;
     434             : 
     435          21 :     *got_frame = 1;
     436             : 
     437          21 :     return avpkt->size;
     438             : }
     439             : 
     440             : AVCodec ff_xan_wc4_decoder = {
     441             :     .name           = "xan_wc4",
     442             :     .long_name      = NULL_IF_CONFIG_SMALL("Wing Commander IV / Xxan"),
     443             :     .type           = AVMEDIA_TYPE_VIDEO,
     444             :     .id             = AV_CODEC_ID_XAN_WC4,
     445             :     .priv_data_size = sizeof(XanContext),
     446             :     .init           = xan_decode_init,
     447             :     .close          = xan_decode_end,
     448             :     .decode         = xan_decode_frame,
     449             :     .capabilities   = AV_CODEC_CAP_DR1,
     450             : };

Generated by: LCOV version 1.13