Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. #include "avcodec.h"
  32. #define BITSTREAM_READER_LE
  33. #include "get_bits.h"
  34. #include "bytestream.h"
  35. #include "idctdsp.h"
  36. #include "aandcttab.h"
  37. #include "eaidct.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. static av_cold int tgq_decode_init(AVCodecContext *avctx)
  50. {
  51.     TgqContext *s = avctx->priv_data;
  52.     uint8_t idct_permutation[64];
  53.     s->avctx = avctx;
  54.     ff_init_scantable_permutation(idct_permutation, FF_IDCT_PERM_NONE);
  55.     ff_init_scantable(idct_permutation, &s->scantable, ff_zigzag_direct);
  56.     avctx->framerate = (AVRational){ 15, 1 };
  57.     avctx->pix_fmt   = AV_PIX_FMT_YUV420P;
  58.     return 0;
  59. }
  60.  
  61. static void tgq_decode_block(TgqContext *s, int16_t block[64], GetBitContext *gb)
  62. {
  63.     uint8_t *perm = s->scantable.permutated;
  64.     int i, j, value;
  65.     block[0] = get_sbits(gb, 8) * s->qtable[0];
  66.     for (i = 1; i < 64;) {
  67.         switch (show_bits(gb, 3)) {
  68.         case 4:
  69.             block[perm[i++]] = 0;
  70.         case 0:
  71.             block[perm[i++]] = 0;
  72.             skip_bits(gb, 3);
  73.             break;
  74.         case 5:
  75.         case 1:
  76.             skip_bits(gb, 2);
  77.             value = get_bits(gb, 6);
  78.             for (j = 0; j < value; j++)
  79.                 block[perm[i++]] = 0;
  80.             break;
  81.         case 6:
  82.             skip_bits(gb, 3);
  83.             block[perm[i]] = -s->qtable[perm[i]];
  84.             i++;
  85.             break;
  86.         case 2:
  87.             skip_bits(gb, 3);
  88.             block[perm[i]] = s->qtable[perm[i]];
  89.             i++;
  90.             break;
  91.         case 7: // 111b
  92.         case 3: // 011b
  93.             skip_bits(gb, 2);
  94.             if (show_bits(gb, 6) == 0x3F) {
  95.                 skip_bits(gb, 6);
  96.                 block[perm[i]] = get_sbits(gb, 8) * s->qtable[perm[i]];
  97.             } else {
  98.                 block[perm[i]] = get_sbits(gb, 6) * s->qtable[perm[i]];
  99.             }
  100.             i++;
  101.             break;
  102.         }
  103.     }
  104.     block[0] += 128 << 4;
  105. }
  106.  
  107. static void tgq_idct_put_mb(TgqContext *s, int16_t (*block)[64], AVFrame *frame,
  108.                             int mb_x, int mb_y)
  109. {
  110.     int linesize = frame->linesize[0];
  111.     uint8_t *dest_y  = frame->data[0] + (mb_y * 16 * linesize)           + mb_x * 16;
  112.     uint8_t *dest_cb = frame->data[1] + (mb_y * 8  * frame->linesize[1]) + mb_x * 8;
  113.     uint8_t *dest_cr = frame->data[2] + (mb_y * 8  * frame->linesize[2]) + mb_x * 8;
  114.  
  115.     ff_ea_idct_put_c(dest_y                   , linesize, block[0]);
  116.     ff_ea_idct_put_c(dest_y                + 8, linesize, block[1]);
  117.     ff_ea_idct_put_c(dest_y + 8 * linesize    , linesize, block[2]);
  118.     ff_ea_idct_put_c(dest_y + 8 * linesize + 8, linesize, block[3]);
  119.     if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
  120.          ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]);
  121.          ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]);
  122.     }
  123. }
  124.  
  125. static inline void tgq_dconly(TgqContext *s, unsigned char *dst,
  126.                               int dst_stride, int dc)
  127. {
  128.     int level = av_clip_uint8((dc*s->qtable[0] + 2056) >> 4);
  129.     int j;
  130.     for (j = 0; j < 8; j++)
  131.         memset(dst + j * dst_stride, level, 8);
  132. }
  133.  
  134. static void tgq_idct_put_mb_dconly(TgqContext *s, AVFrame *frame,
  135.                                    int mb_x, int mb_y, const int8_t *dc)
  136. {
  137.     int linesize = frame->linesize[0];
  138.     uint8_t *dest_y  = frame->data[0] + (mb_y * 16 * linesize)             + mb_x * 16;
  139.     uint8_t *dest_cb = frame->data[1] + (mb_y * 8  * frame->linesize[1]) + mb_x * 8;
  140.     uint8_t *dest_cr = frame->data[2] + (mb_y * 8  * frame->linesize[2]) + mb_x * 8;
  141.     tgq_dconly(s, dest_y,                    linesize, dc[0]);
  142.     tgq_dconly(s, dest_y                + 8, linesize, dc[1]);
  143.     tgq_dconly(s, dest_y + 8 * linesize,     linesize, dc[2]);
  144.     tgq_dconly(s, dest_y + 8 * linesize + 8, linesize, dc[3]);
  145.     if (!(s->avctx->flags & AV_CODEC_FLAG_GRAY)) {
  146.         tgq_dconly(s, dest_cb, frame->linesize[1], dc[4]);
  147.         tgq_dconly(s, dest_cr, frame->linesize[2], dc[5]);
  148.     }
  149. }
  150.  
  151. 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.     mode = bytestream2_get_byte(&s->gb);
  158.     if (mode > 12) {
  159.         GetBitContext gb;
  160.         int ret = init_get_bits8(&gb, s->gb.buffer, FFMIN(bytestream2_get_bytes_left(&s->gb), mode));
  161.         if (ret < 0)
  162.             return ret;
  163.  
  164.         for (i = 0; i < 6; i++)
  165.             tgq_decode_block(s, s->block[i], &gb);
  166.         tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y);
  167.         bytestream2_skip(&s->gb, mode);
  168.     } else {
  169.         if (mode == 3) {
  170.             memset(dc, bytestream2_get_byte(&s->gb), 4);
  171.             dc[4] = bytestream2_get_byte(&s->gb);
  172.             dc[5] = bytestream2_get_byte(&s->gb);
  173.         } else if (mode == 6) {
  174.             bytestream2_get_buffer(&s->gb, dc, 6);
  175.         } else if (mode == 12) {
  176.             for (i = 0; i < 6; i++) {
  177.                 dc[i] = bytestream2_get_byte(&s->gb);
  178.                 bytestream2_skip(&s->gb, 1);
  179.             }
  180.         } else {
  181.             av_log(s->avctx, AV_LOG_ERROR, "unsupported mb mode %i\n", mode);
  182.             return -1;
  183.         }
  184.         tgq_idct_put_mb_dconly(s, frame, mb_x, mb_y, dc);
  185.     }
  186.     return 0;
  187. }
  188.  
  189. static void tgq_calculate_qtable(TgqContext *s, int quant)
  190. {
  191.     int i, j;
  192.     const int a = (14 * (100 - quant)) / 100 + 1;
  193.     const int b = (11 * (100 - quant)) / 100 + 4;
  194.     for (j = 0; j < 8; j++)
  195.         for (i = 0; i < 8; i++)
  196.             s->qtable[j * 8 + i] = ((a * (j + i) / (7 + 7) + b) *
  197.                                     ff_inv_aanscales[j * 8 + i]) >> (14 - 4);
  198. }
  199.  
  200. static int tgq_decode_frame(AVCodecContext *avctx,
  201.                             void *data, int *got_frame,
  202.                             AVPacket *avpkt)
  203. {
  204.     const uint8_t *buf = avpkt->data;
  205.     int buf_size       = avpkt->size;
  206.     TgqContext *s      = avctx->priv_data;
  207.     AVFrame *frame     = data;
  208.     int x, y, ret;
  209.     int big_endian;
  210.  
  211.     if (buf_size < 16) {
  212.         av_log(avctx, AV_LOG_WARNING, "truncated header\n");
  213.         return AVERROR_INVALIDDATA;
  214.     }
  215.     big_endian = AV_RL32(&buf[4]) > 0x000FFFFF;
  216.     bytestream2_init(&s->gb, buf + 8, buf_size - 8);
  217.     if (big_endian) {
  218.         s->width  = bytestream2_get_be16u(&s->gb);
  219.         s->height = bytestream2_get_be16u(&s->gb);
  220.     } else {
  221.         s->width  = bytestream2_get_le16u(&s->gb);
  222.         s->height = bytestream2_get_le16u(&s->gb);
  223.     }
  224.  
  225.     ret = ff_set_dimensions(s->avctx, s->width, s->height);
  226.     if (ret < 0)
  227.         return ret;
  228.  
  229.     tgq_calculate_qtable(s, bytestream2_get_byteu(&s->gb));
  230.     bytestream2_skip(&s->gb, 3);
  231.  
  232.     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
  233.         return ret;
  234.     frame->key_frame = 1;
  235.     frame->pict_type = AV_PICTURE_TYPE_I;
  236.  
  237.     for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++)
  238.         for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++)
  239.             if (tgq_decode_mb(s, frame, y, x) < 0)
  240.                 return AVERROR_INVALIDDATA;
  241.  
  242.     *got_frame = 1;
  243.  
  244.     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. };
  257.