LCOV - code coverage report
Current view: top level - libavcodec - tiertexseqv.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 111 130 85.4 %
Date: 2017-12-14 19:11:59 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Tiertex Limited SEQ Video Decoder
       3             :  * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net)
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * Tiertex Limited SEQ video decoder
      25             :  */
      26             : 
      27             : #define BITSTREAM_READER_LE
      28             : #include "avcodec.h"
      29             : #include "get_bits.h"
      30             : #include "internal.h"
      31             : 
      32             : 
      33             : typedef struct SeqVideoContext {
      34             :     AVCodecContext *avctx;
      35             :     AVFrame *frame;
      36             : } SeqVideoContext;
      37             : 
      38             : 
      39        2508 : static const unsigned char *seq_unpack_rle_block(const unsigned char *src,
      40             :                                                  const unsigned char *src_end,
      41             :                                                  unsigned char *dst, int dst_size)
      42             : {
      43             :     int i, len, sz;
      44             :     GetBitContext gb;
      45             :     int code_table[64];
      46             : 
      47             :     /* get the rle codes */
      48        2508 :     init_get_bits(&gb, src, (src_end - src) * 8);
      49       53386 :     for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) {
      50       50878 :         if (get_bits_left(&gb) < 4)
      51           0 :             return NULL;
      52       50878 :         code_table[i] = get_sbits(&gb, 4);
      53       50878 :         sz += FFABS(code_table[i]);
      54             :     }
      55        2508 :     src += (get_bits_count(&gb) + 7) / 8;
      56             : 
      57             :     /* do the rle unpacking */
      58       53386 :     for (i = 0; i < 64 && dst_size > 0; i++) {
      59       50878 :         len = code_table[i];
      60       50878 :         if (len < 0) {
      61       50878 :             len = -len;
      62       50878 :             if (src_end - src < 1)
      63           0 :                 return NULL;
      64       50878 :             memset(dst, *src++, FFMIN(len, dst_size));
      65             :         } else {
      66           0 :             if (src_end - src < len)
      67           0 :                 return NULL;
      68           0 :             memcpy(dst, src, FFMIN(len, dst_size));
      69           0 :             src += len;
      70             :         }
      71       50878 :         dst += len;
      72       50878 :         dst_size -= len;
      73             :     }
      74        2508 :     return src;
      75             : }
      76             : 
      77        6758 : static const unsigned char *seq_decode_op1(SeqVideoContext *seq,
      78             :                                            const unsigned char *src,
      79             :                                            const unsigned char *src_end,
      80             :                                            unsigned char *dst)
      81             : {
      82             :     const unsigned char *color_table;
      83             :     int b, i, len, bits;
      84             :     GetBitContext gb;
      85             :     unsigned char block[8 * 8];
      86             : 
      87        6758 :     if (src_end - src < 1)
      88           0 :         return NULL;
      89        6758 :     len = *src++;
      90        6758 :     if (len & 0x80) {
      91        2508 :         switch (len & 3) {
      92        1099 :         case 1:
      93        1099 :             src = seq_unpack_rle_block(src, src_end, block, sizeof(block));
      94        9891 :             for (b = 0; b < 8; b++) {
      95        8792 :                 memcpy(dst, &block[b * 8], 8);
      96        8792 :                 dst += seq->frame->linesize[0];
      97             :             }
      98        1099 :             break;
      99        1409 :         case 2:
     100        1409 :             src = seq_unpack_rle_block(src, src_end, block, sizeof(block));
     101       12681 :             for (i = 0; i < 8; i++) {
     102      101448 :                 for (b = 0; b < 8; b++)
     103       90176 :                     dst[b * seq->frame->linesize[0]] = block[i * 8 + b];
     104       11272 :                 ++dst;
     105             :             }
     106        1409 :             break;
     107             :         }
     108             :     } else {
     109        4250 :         if (len <= 0)
     110           0 :             return NULL;
     111        4250 :         bits = ff_log2_tab[len - 1] + 1;
     112        4250 :         if (src_end - src < len + 8 * bits)
     113           0 :             return NULL;
     114        4250 :         color_table = src;
     115        4250 :         src += len;
     116        4250 :         init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8;
     117       38250 :         for (b = 0; b < 8; b++) {
     118      306000 :             for (i = 0; i < 8; i++)
     119      272000 :                 dst[i] = color_table[get_bits(&gb, bits)];
     120       34000 :             dst += seq->frame->linesize[0];
     121             :         }
     122             :     }
     123             : 
     124        6758 :     return src;
     125             : }
     126             : 
     127         197 : static const unsigned char *seq_decode_op2(SeqVideoContext *seq,
     128             :                                            const unsigned char *src,
     129             :                                            const unsigned char *src_end,
     130             :                                            unsigned char *dst)
     131             : {
     132             :     int i;
     133             : 
     134         197 :     if (src_end - src < 8 * 8)
     135           0 :         return NULL;
     136             : 
     137        1773 :     for (i = 0; i < 8; i++) {
     138        1576 :         memcpy(dst, src, 8);
     139        1576 :         src += 8;
     140        1576 :         dst += seq->frame->linesize[0];
     141             :     }
     142             : 
     143         197 :     return src;
     144             : }
     145             : 
     146        3101 : static const unsigned char *seq_decode_op3(SeqVideoContext *seq,
     147             :                                            const unsigned char *src,
     148             :                                            const unsigned char *src_end,
     149             :                                            unsigned char *dst)
     150             : {
     151             :     int pos, offset;
     152             : 
     153             :     do {
     154        3101 :         if (src_end - src < 2)
     155           0 :             return NULL;
     156        3101 :         pos = *src++;
     157        3101 :         offset = ((pos >> 3) & 7) * seq->frame->linesize[0] + (pos & 7);
     158        3101 :         dst[offset] = *src++;
     159        3101 :     } while (!(pos & 0x80));
     160             : 
     161         595 :     return src;
     162             : }
     163             : 
     164          21 : static int seqvideo_decode(SeqVideoContext *seq, const unsigned char *data, int data_size)
     165             : {
     166          21 :     const unsigned char *data_end = data + data_size;
     167             :     GetBitContext gb;
     168             :     int flags, i, j, x, y, op;
     169             :     unsigned char c[3];
     170             :     unsigned char *dst;
     171             :     uint32_t *palette;
     172             : 
     173          21 :     flags = *data++;
     174             : 
     175          21 :     if (flags & 1) {
     176          21 :         palette = (uint32_t *)seq->frame->data[1];
     177          21 :         if (data_end - data < 256 * 3)
     178           0 :             return AVERROR_INVALIDDATA;
     179        5397 :         for (i = 0; i < 256; i++) {
     180       21504 :             for (j = 0; j < 3; j++, data++)
     181       16128 :                 c[j] = (*data << 2) | (*data >> 4);
     182        5376 :             palette[i] = 0xFFU << 24 | AV_RB24(c);
     183             :         }
     184          21 :         seq->frame->palette_has_changed = 1;
     185             :     }
     186             : 
     187          21 :     if (flags & 2) {
     188          21 :         if (data_end - data < 128)
     189           0 :             return AVERROR_INVALIDDATA;
     190          21 :         init_get_bits(&gb, data, 128 * 8); data += 128;
     191         357 :         for (y = 0; y < 128; y += 8)
     192       11088 :             for (x = 0; x < 256; x += 8) {
     193       10752 :                 dst = &seq->frame->data[0][y * seq->frame->linesize[0] + x];
     194       10752 :                 op = get_bits(&gb, 2);
     195       10752 :                 switch (op) {
     196        6758 :                 case 1:
     197        6758 :                     data = seq_decode_op1(seq, data, data_end, dst);
     198        6758 :                     break;
     199         197 :                 case 2:
     200         197 :                     data = seq_decode_op2(seq, data, data_end, dst);
     201         197 :                     break;
     202         595 :                 case 3:
     203         595 :                     data = seq_decode_op3(seq, data, data_end, dst);
     204         595 :                     break;
     205             :                 }
     206       10752 :                 if (!data)
     207           0 :                     return AVERROR_INVALIDDATA;
     208             :             }
     209             :     }
     210          21 :     return 0;
     211             : }
     212             : 
     213           2 : static av_cold int seqvideo_decode_init(AVCodecContext *avctx)
     214             : {
     215           2 :     SeqVideoContext *seq = avctx->priv_data;
     216             :     int ret;
     217             : 
     218           2 :     seq->avctx = avctx;
     219           2 :     avctx->pix_fmt = AV_PIX_FMT_PAL8;
     220             : 
     221           2 :     ret = ff_set_dimensions(avctx, 256, 128);
     222           2 :     if (ret < 0)
     223           0 :         return ret;
     224             : 
     225           2 :     seq->frame = av_frame_alloc();
     226           2 :     if (!seq->frame)
     227           0 :         return AVERROR(ENOMEM);
     228             : 
     229           2 :     return 0;
     230             : }
     231             : 
     232          21 : static int seqvideo_decode_frame(AVCodecContext *avctx,
     233             :                                  void *data, int *got_frame,
     234             :                                  AVPacket *avpkt)
     235             : {
     236          21 :     const uint8_t *buf = avpkt->data;
     237          21 :     int buf_size = avpkt->size;
     238             :     int ret;
     239             : 
     240          21 :     SeqVideoContext *seq = avctx->priv_data;
     241             : 
     242          21 :     if ((ret = ff_reget_buffer(avctx, seq->frame)) < 0)
     243           0 :         return ret;
     244             : 
     245          21 :     if (seqvideo_decode(seq, buf, buf_size))
     246           0 :         return AVERROR_INVALIDDATA;
     247             : 
     248          21 :     if ((ret = av_frame_ref(data, seq->frame)) < 0)
     249           0 :         return ret;
     250          21 :     *got_frame       = 1;
     251             : 
     252          21 :     return buf_size;
     253             : }
     254             : 
     255           2 : static av_cold int seqvideo_decode_end(AVCodecContext *avctx)
     256             : {
     257           2 :     SeqVideoContext *seq = avctx->priv_data;
     258             : 
     259           2 :     av_frame_free(&seq->frame);
     260             : 
     261           2 :     return 0;
     262             : }
     263             : 
     264             : AVCodec ff_tiertexseqvideo_decoder = {
     265             :     .name           = "tiertexseqvideo",
     266             :     .long_name      = NULL_IF_CONFIG_SMALL("Tiertex Limited SEQ video"),
     267             :     .type           = AVMEDIA_TYPE_VIDEO,
     268             :     .id             = AV_CODEC_ID_TIERTEXSEQVIDEO,
     269             :     .priv_data_size = sizeof(SeqVideoContext),
     270             :     .init           = seqvideo_decode_init,
     271             :     .close          = seqvideo_decode_end,
     272             :     .decode         = seqvideo_decode_frame,
     273             :     .capabilities   = AV_CODEC_CAP_DR1,
     274             : };

Generated by: LCOV version 1.13