Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 "dsputil.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_NO_IDCT_PERM);
  55.     ff_init_scantable(idct_permutation, &s->scantable, ff_zigzag_direct);
  56.     avctx->time_base = (AVRational){1, 15};
  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 & 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 & 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.         init_get_bits8(&gb, s->gb.buffer, FFMIN(bytestream2_get_bytes_left(&s->gb), mode));
  161.         for (i = 0; i < 6; i++)
  162.             tgq_decode_block(s, s->block[i], &gb);
  163.         tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y);
  164.         bytestream2_skip(&s->gb, mode);
  165.     } else {
  166.         if (mode == 3) {
  167.             memset(dc, bytestream2_get_byte(&s->gb), 4);
  168.             dc[4] = bytestream2_get_byte(&s->gb);
  169.             dc[5] = bytestream2_get_byte(&s->gb);
  170.         } else if (mode == 6) {
  171.             bytestream2_get_buffer(&s->gb, dc, 6);
  172.         } else if (mode == 12) {
  173.             for (i = 0; i < 6; i++) {
  174.                 dc[i] = bytestream2_get_byte(&s->gb);
  175.                 bytestream2_skip(&s->gb, 1);
  176.             }
  177.         } else {
  178.             av_log(s->avctx, AV_LOG_ERROR, "unsupported mb mode %i\n", mode);
  179.             return -1;
  180.         }
  181.         tgq_idct_put_mb_dconly(s, frame, mb_x, mb_y, dc);
  182.     }
  183.     return 0;
  184. }
  185.  
  186. static void tgq_calculate_qtable(TgqContext *s, int quant)
  187. {
  188.     int i, j;
  189.     const int a = (14 * (100 - quant)) / 100 + 1;
  190.     const int b = (11 * (100 - quant)) / 100 + 4;
  191.     for (j = 0; j < 8; j++)
  192.         for (i = 0; i < 8; i++)
  193.             s->qtable[j * 8 + i] = ((a * (j + i) / (7 + 7) + b) *
  194.                                     ff_inv_aanscales[j * 8 + i]) >> (14 - 4);
  195. }
  196.  
  197. static int tgq_decode_frame(AVCodecContext *avctx,
  198.                             void *data, int *got_frame,
  199.                             AVPacket *avpkt)
  200. {
  201.     const uint8_t *buf = avpkt->data;
  202.     int buf_size       = avpkt->size;
  203.     TgqContext *s      = avctx->priv_data;
  204.     AVFrame *frame     = data;
  205.     int x, y, ret;
  206.     int big_endian;
  207.  
  208.     if (buf_size < 16) {
  209.         av_log(avctx, AV_LOG_WARNING, "truncated header\n");
  210.         return AVERROR_INVALIDDATA;
  211.     }
  212.     big_endian = AV_RL32(&buf[4]) > 0x000FFFFF;
  213.     bytestream2_init(&s->gb, buf + 8, buf_size - 8);
  214.     if (big_endian) {
  215.         s->width  = bytestream2_get_be16u(&s->gb);
  216.         s->height = bytestream2_get_be16u(&s->gb);
  217.     } else {
  218.         s->width  = bytestream2_get_le16u(&s->gb);
  219.         s->height = bytestream2_get_le16u(&s->gb);
  220.     }
  221.  
  222.     if (s->avctx->width!=s->width || s->avctx->height!=s->height) {
  223.         avcodec_set_dimensions(s->avctx, s->width, s->height);
  224.     }
  225.     tgq_calculate_qtable(s, bytestream2_get_byteu(&s->gb));
  226.     bytestream2_skip(&s->gb, 3);
  227.  
  228.     if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
  229.         return ret;
  230.     frame->key_frame = 1;
  231.     frame->pict_type = AV_PICTURE_TYPE_I;
  232.  
  233.     for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++)
  234.         for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++)
  235.             if (tgq_decode_mb(s, frame, y, x) < 0)
  236.                 return AVERROR_INVALIDDATA;
  237.  
  238.     *got_frame = 1;
  239.  
  240.     return avpkt->size;
  241. }
  242.  
  243. AVCodec ff_eatgq_decoder = {
  244.     .name           = "eatgq",
  245.     .long_name      = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"),
  246.     .type           = AVMEDIA_TYPE_VIDEO,
  247.     .id             = AV_CODEC_ID_TGQ,
  248.     .priv_data_size = sizeof(TgqContext),
  249.     .init           = tgq_decode_init,
  250.     .decode         = tgq_decode_frame,
  251.     .capabilities   = CODEC_CAP_DR1,
  252. };
  253.