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 40typedef 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 49static 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 61static 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 107static 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 125static 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 134static 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 151static 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 186static 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 197static 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 ret = ff_set_dimensions(s->avctx, s->width, s->height); 223 if (ret < 0) 224 return ret; 225 226 tgq_calculate_qtable(s, bytestream2_get_byteu(&s->gb)); 227 bytestream2_skip(&s->gb, 3); 228 229 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) 230 return ret; 231 frame->key_frame = 1; 232 frame->pict_type = AV_PICTURE_TYPE_I; 233 234 for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++) 235 for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++) 236 if (tgq_decode_mb(s, frame, y, x) < 0) 237 return AVERROR_INVALIDDATA; 238 239 *got_frame = 1; 240 241 return avpkt->size; 242} 243 244AVCodec ff_eatgq_decoder = { 245 .name = "eatgq", 246 .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"), 247 .type = AVMEDIA_TYPE_VIDEO, 248 .id = AV_CODEC_ID_TGQ, 249 .priv_data_size = sizeof(TgqContext), 250 .init = tgq_decode_init, 251 .decode = tgq_decode_frame, 252 .capabilities = CODEC_CAP_DR1, 253}; 254