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