LCOV - code coverage report
Current view: top level - libavcodec - eatgq.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 124 138 89.9 %
Date: 2017-12-11 04:34:20 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Electronic Arts TGQ Video Decoder
       3             :  * Copyright (c) 2007-2008 Peter Ross <pross@xvid.org>
       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 St, Fifth Floor, Boston, MA  02110-1301  USA
      20             :  */
      21             : 
      22             : /**
      23             :  * @file
      24             :  * Electronic Arts TGQ Video Decoder
      25             :  * @author Peter Ross <pross@xvid.org>
      26             :  *
      27             :  * Technical details here:
      28             :  * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TGQ
      29             :  */
      30             : 
      31             : #define BITSTREAM_READER_LE
      32             : #include "aandcttab.h"
      33             : #include "avcodec.h"
      34             : #include "bytestream.h"
      35             : #include "eaidct.h"
      36             : #include "get_bits.h"
      37             : #include "idctdsp.h"
      38             : #include "internal.h"
      39             : 
      40             : typedef struct TgqContext {
      41             :     AVCodecContext *avctx;
      42             :     int width, height;
      43             :     ScanTable scantable;
      44             :     int qtable[64];
      45             :     DECLARE_ALIGNED(16, int16_t, block)[6][64];
      46             :     GetByteContext gb;
      47             : } TgqContext;
      48             : 
      49           2 : static av_cold int tgq_decode_init(AVCodecContext *avctx)
      50             : {
      51           2 :     TgqContext *s = avctx->priv_data;
      52             :     uint8_t idct_permutation[64];
      53           2 :     s->avctx = avctx;
      54           2 :     ff_init_scantable_permutation(idct_permutation, FF_IDCT_PERM_NONE);
      55           2 :     ff_init_scantable(idct_permutation, &s->scantable, ff_zigzag_direct);
      56           2 :     avctx->framerate = (AVRational){ 15, 1 };
      57           2 :     avctx->pix_fmt   = AV_PIX_FMT_YUV420P;
      58           2 :     return 0;
      59             : }
      60             : 
      61      101826 : static void tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb)
      62             : {
      63      101826 :     uint8_t *perm = s->scantable.permutated;
      64             :     int i, j, value;
      65      101826 :     block[0] = get_sbits(gb, 8) * s->qtable[0];
      66     1667179 :     for (i = 1; i < 64;) {
      67     1463527 :         switch (show_bits(gb, 3)) {
      68      152397 :         case 4:
      69      152397 :             block[perm[i++]] = 0;
      70      370656 :         case 0:
      71      370656 :             block[perm[i++]] = 0;
      72      370656 :             skip_bits(gb, 3);
      73      370656 :             break;
      74      148778 :         case 5:
      75             :         case 1:
      76      148778 :             skip_bits(gb, 2);
      77      148778 :             value = get_bits(gb, 6);
      78     5096670 :             for (j = 0; j < value; j++)
      79     4947892 :                 block[perm[i++]] = 0;
      80      148778 :             break;
      81      333783 :         case 6:
      82      333783 :             skip_bits(gb, 3);
      83      333783 :             block[perm[i]] = -s->qtable[perm[i]];
      84      333783 :             i++;
      85      333783 :             break;
      86      339292 :         case 2:
      87      339292 :             skip_bits(gb, 3);
      88      339292 :             block[perm[i]] = s->qtable[perm[i]];
      89      339292 :             i++;
      90      339292 :             break;
      91      271018 :         case 7: // 111b
      92             :         case 3: // 011b
      93      271018 :             skip_bits(gb, 2);
      94      271018 :             if (show_bits(gb, 6) == 0x3F) {
      95        1440 :                 skip_bits(gb, 6);
      96        1440 :                 block[perm[i]] = get_sbits(gb, 8) * s->qtable[perm[i]];
      97             :             } else {
      98      269578 :                 block[perm[i]] = get_sbits(gb, 6) * s->qtable[perm[i]];
      99             :             }
     100      271018 :             i++;
     101      271018 :             break;
     102             :         }
     103             :     }
     104      101826 :     block[0] += 128 << 4;
     105      101826 : }
     106             : 
     107       16971 : static void tgq_idct_put_mb(TgqContext *s, int16_t (*block)[64], AVFrame *frame,
     108             :                             int mb_x, int mb_y)
     109             : {
     110       16971 :     ptrdiff_t linesize = frame->linesize[0];
     111       16971 :     uint8_t *dest_y  = frame->data[0] + (mb_y * 16 * linesize)           + mb_x * 16;
     112       16971 :     uint8_t *dest_cb = frame->data[1] + (mb_y * 8  * frame->linesize[1]) + mb_x * 8;
     113       16971 :     uint8_t *dest_cr = frame->data[2] + (mb_y * 8  * frame->linesize[2]) + mb_x * 8;
     114             : 
     115       16971 :     ff_ea_idct_put_c(dest_y                   , linesize, block[0]);
     116       16971 :     ff_ea_idct_put_c(dest_y                + 8, linesize, block[1]);
     117       16971 :     ff_ea_idct_put_c(dest_y + 8 * linesize    , linesize, block[2]);
     118       16971 :     ff_ea_idct_put_c(dest_y + 8 * linesize + 8, linesize, block[3]);
     119       16971 :     if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
     120       16971 :          ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]);
     121       16971 :          ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]);
     122             :     }
     123       16971 : }
     124             : 
     125       50508 : static inline void tgq_dconly(TgqContext *s, unsigned char *dst,
     126             :                               ptrdiff_t dst_stride, int dc)
     127             : {
     128       50508 :     int level = av_clip_uint8((dc*s->qtable[0] + 2056) >> 4);
     129             :     int j;
     130      454572 :     for (j = 0; j < 8; j++)
     131      404064 :         memset(dst + j * dst_stride, level, 8);
     132       50508 : }
     133             : 
     134        8418 : static void tgq_idct_put_mb_dconly(TgqContext *s, AVFrame *frame,
     135             :                                    int mb_x, int mb_y, const int8_t *dc)
     136             : {
     137        8418 :     ptrdiff_t linesize = frame->linesize[0];
     138        8418 :     uint8_t *dest_y  = frame->data[0] + (mb_y * 16 * linesize)             + mb_x * 16;
     139        8418 :     uint8_t *dest_cb = frame->data[1] + (mb_y * 8  * frame->linesize[1]) + mb_x * 8;
     140        8418 :     uint8_t *dest_cr = frame->data[2] + (mb_y * 8  * frame->linesize[2]) + mb_x * 8;
     141        8418 :     tgq_dconly(s, dest_y,                    linesize, dc[0]);
     142        8418 :     tgq_dconly(s, dest_y                + 8, linesize, dc[1]);
     143        8418 :     tgq_dconly(s, dest_y + 8 * linesize,     linesize, dc[2]);
     144        8418 :     tgq_dconly(s, dest_y + 8 * linesize + 8, linesize, dc[3]);
     145        8418 :     if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
     146        8418 :         tgq_dconly(s, dest_cb, frame->linesize[1], dc[4]);
     147        8418 :         tgq_dconly(s, dest_cr, frame->linesize[2], dc[5]);
     148             :     }
     149        8418 : }
     150             : 
     151       25389 : static int tgq_decode_mb(TgqContext *s, AVFrame *frame, int mb_y, int mb_x)
     152             : {
     153             :     int mode;
     154             :     int i;
     155             :     int8_t dc[6];
     156             : 
     157       25389 :     mode = bytestream2_get_byte(&s->gb);
     158       25389 :     if (mode > 12) {
     159             :         GetBitContext gb;
     160       16971 :         int ret = init_get_bits8(&gb, s->gb.buffer, FFMIN(bytestream2_get_bytes_left(&s->gb), mode));
     161       16971 :         if (ret < 0)
     162           0 :             return ret;
     163             : 
     164      118797 :         for (i = 0; i < 6; i++)
     165      101826 :             tgq_decode_block(s, s->block[i], &gb);
     166       16971 :         tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y);
     167       16971 :         bytestream2_skip(&s->gb, mode);
     168             :     } else {
     169        8418 :         if (mode == 3) {
     170           0 :             memset(dc, bytestream2_get_byte(&s->gb), 4);
     171           0 :             dc[4] = bytestream2_get_byte(&s->gb);
     172           0 :             dc[5] = bytestream2_get_byte(&s->gb);
     173        8418 :         } else if (mode == 6) {
     174           0 :             bytestream2_get_buffer(&s->gb, dc, 6);
     175        8418 :         } else if (mode == 12) {
     176       58926 :             for (i = 0; i < 6; i++) {
     177       50508 :                 dc[i] = bytestream2_get_byte(&s->gb);
     178       50508 :                 bytestream2_skip(&s->gb, 1);
     179             :             }
     180             :         } else {
     181           0 :             av_log(s->avctx, AV_LOG_ERROR, "unsupported mb mode %i\n", mode);
     182           0 :             return -1;
     183             :         }
     184        8418 :         tgq_idct_put_mb_dconly(s, frame, mb_x, mb_y, dc);
     185             :     }
     186       25389 :     return 0;
     187             : }
     188             : 
     189         279 : static void tgq_calculate_qtable(TgqContext *s, int quant)
     190             : {
     191             :     int i, j;
     192         279 :     const int a = (14 * (100 - quant)) / 100 + 1;
     193         279 :     const int b = (11 * (100 - quant)) / 100 + 4;
     194        2511 :     for (j = 0; j < 8; j++)
     195       20088 :         for (i = 0; i < 8; i++)
     196       53568 :             s->qtable[j * 8 + i] = ((a * (j + i) / (7 + 7) + b) *
     197       35712 :                                     ff_inv_aanscales[j * 8 + i]) >> (14 - 4);
     198         279 : }
     199             : 
     200         279 : static int tgq_decode_frame(AVCodecContext *avctx,
     201             :                             void *data, int *got_frame,
     202             :                             AVPacket *avpkt)
     203             : {
     204         279 :     const uint8_t *buf = avpkt->data;
     205         279 :     int buf_size       = avpkt->size;
     206         279 :     TgqContext *s      = avctx->priv_data;
     207         279 :     AVFrame *frame     = data;
     208             :     int x, y, ret;
     209             :     int big_endian;
     210             : 
     211         279 :     if (buf_size < 16) {
     212           0 :         av_log(avctx, AV_LOG_WARNING, "truncated header\n");
     213           0 :         return AVERROR_INVALIDDATA;
     214             :     }
     215         279 :     big_endian = AV_RL32(&buf[4]) > 0x000FFFFF;
     216         279 :     bytestream2_init(&s->gb, buf + 8, buf_size - 8);
     217         279 :     if (big_endian) {
     218         279 :         s->width  = bytestream2_get_be16u(&s->gb);
     219         279 :         s->height = bytestream2_get_be16u(&s->gb);
     220             :     } else {
     221           0 :         s->width  = bytestream2_get_le16u(&s->gb);
     222           0 :         s->height = bytestream2_get_le16u(&s->gb);
     223             :     }
     224             : 
     225         279 :     ret = ff_set_dimensions(s->avctx, s->width, s->height);
     226         279 :     if (ret < 0)
     227           0 :         return ret;
     228             : 
     229         279 :     tgq_calculate_qtable(s, bytestream2_get_byteu(&s->gb));
     230         279 :     bytestream2_skip(&s->gb, 3);
     231             : 
     232         279 :     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
     233           0 :         return ret;
     234         279 :     frame->key_frame = 1;
     235         279 :     frame->pict_type = AV_PICTURE_TYPE_I;
     236             : 
     237        2232 :     for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++)
     238       27342 :         for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++)
     239       25389 :             if (tgq_decode_mb(s, frame, y, x) < 0)
     240           0 :                 return AVERROR_INVALIDDATA;
     241             : 
     242         279 :     *got_frame = 1;
     243             : 
     244         279 :     return avpkt->size;
     245             : }
     246             : 
     247             : AVCodec ff_eatgq_decoder = {
     248             :     .name           = "eatgq",
     249             :     .long_name      = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"),
     250             :     .type           = AVMEDIA_TYPE_VIDEO,
     251             :     .id             = AV_CODEC_ID_TGQ,
     252             :     .priv_data_size = sizeof(TgqContext),
     253             :     .init           = tgq_decode_init,
     254             :     .decode         = tgq_decode_frame,
     255             :     .capabilities   = AV_CODEC_CAP_DR1,
     256             : };

Generated by: LCOV version 1.13