Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * Electronic Arts TQI Video Decoder | |
3 | * Copyright (c) 2007-2009 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 TQI Video Decoder | |
25 | * @author Peter Ross <pross@xvid.org> | |
26 | * @see http://wiki.multimedia.cx/index.php?title=Electronic_Arts_TQI | |
27 | */ | |
28 | ||
29 | #include "avcodec.h" | |
30 | #include "blockdsp.h" | |
31 | #include "bswapdsp.h" | |
32 | #include "get_bits.h" | |
33 | #include "aandcttab.h" | |
34 | #include "eaidct.h" | |
35 | #include "idctdsp.h" | |
36 | #include "internal.h" | |
37 | #include "mpeg12.h" | |
38 | #include "mpegvideo.h" | |
39 | ||
40 | typedef struct TqiContext { | |
41 | MpegEncContext s; | |
42 | BswapDSPContext bsdsp; | |
43 | void *bitstream_buf; | |
44 | unsigned int bitstream_buf_size; | |
45 | DECLARE_ALIGNED(16, int16_t, block)[6][64]; | |
46 | } TqiContext; | |
47 | ||
48 | static av_cold int tqi_decode_init(AVCodecContext *avctx) | |
49 | { | |
50 | TqiContext *t = avctx->priv_data; | |
51 | MpegEncContext *s = &t->s; | |
52 | s->avctx = avctx; | |
53 | ff_blockdsp_init(&s->bdsp, avctx); | |
54 | ff_bswapdsp_init(&t->bsdsp); | |
55 | ff_idctdsp_init(&s->idsp, avctx); | |
56 | ff_init_scantable_permutation(s->idsp.idct_permutation, FF_IDCT_PERM_NONE); | |
57 | ff_init_scantable(s->idsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); | |
58 | s->qscale = 1; | |
f6fa7814 | 59 | avctx->framerate = (AVRational){ 15, 1 }; |
2ba45a60 DM |
60 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; |
61 | ff_mpeg12_init_vlcs(); | |
62 | return 0; | |
63 | } | |
64 | ||
65 | static int tqi_decode_mb(MpegEncContext *s, int16_t (*block)[64]) | |
66 | { | |
67 | int n; | |
68 | s->bdsp.clear_blocks(block[0]); | |
69 | for (n=0; n<6; n++) | |
70 | if (ff_mpeg1_decode_block_intra(s, block[n], n) < 0) | |
71 | return -1; | |
72 | ||
73 | return 0; | |
74 | } | |
75 | ||
76 | static inline void tqi_idct_put(TqiContext *t, AVFrame *frame, int16_t (*block)[64]) | |
77 | { | |
78 | MpegEncContext *s = &t->s; | |
79 | int linesize = frame->linesize[0]; | |
80 | uint8_t *dest_y = frame->data[0] + (s->mb_y * 16* linesize ) + s->mb_x * 16; | |
81 | uint8_t *dest_cb = frame->data[1] + (s->mb_y * 8 * frame->linesize[1]) + s->mb_x * 8; | |
82 | uint8_t *dest_cr = frame->data[2] + (s->mb_y * 8 * frame->linesize[2]) + s->mb_x * 8; | |
83 | ||
84 | ff_ea_idct_put_c(dest_y , linesize, block[0]); | |
85 | ff_ea_idct_put_c(dest_y + 8, linesize, block[1]); | |
86 | ff_ea_idct_put_c(dest_y + 8*linesize , linesize, block[2]); | |
87 | ff_ea_idct_put_c(dest_y + 8*linesize + 8, linesize, block[3]); | |
88 | if(!(s->avctx->flags&CODEC_FLAG_GRAY)) { | |
89 | ff_ea_idct_put_c(dest_cb, frame->linesize[1], block[4]); | |
90 | ff_ea_idct_put_c(dest_cr, frame->linesize[2], block[5]); | |
91 | } | |
92 | } | |
93 | ||
94 | static void tqi_calculate_qtable(MpegEncContext *s, int quant) | |
95 | { | |
96 | const int qscale = (215 - 2*quant)*5; | |
97 | int i; | |
98 | s->intra_matrix[0] = (ff_inv_aanscales[0]*ff_mpeg1_default_intra_matrix[0])>>11; | |
99 | for(i=1; i<64; i++) | |
100 | s->intra_matrix[i] = (ff_inv_aanscales[i]*ff_mpeg1_default_intra_matrix[i]*qscale + 32)>>14; | |
101 | } | |
102 | ||
103 | static int tqi_decode_frame(AVCodecContext *avctx, | |
104 | void *data, int *got_frame, | |
105 | AVPacket *avpkt) | |
106 | { | |
107 | const uint8_t *buf = avpkt->data; | |
108 | int buf_size = avpkt->size; | |
109 | const uint8_t *buf_end = buf+buf_size; | |
110 | TqiContext *t = avctx->priv_data; | |
111 | MpegEncContext *s = &t->s; | |
112 | AVFrame *frame = data; | |
113 | int ret; | |
114 | ||
115 | s->width = AV_RL16(&buf[0]); | |
116 | s->height = AV_RL16(&buf[2]); | |
117 | tqi_calculate_qtable(s, buf[4]); | |
118 | buf += 8; | |
119 | ||
120 | ret = ff_set_dimensions(s->avctx, s->width, s->height); | |
121 | if (ret < 0) | |
122 | return ret; | |
123 | ||
124 | if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) | |
125 | return ret; | |
126 | ||
127 | av_fast_padded_malloc(&t->bitstream_buf, &t->bitstream_buf_size, | |
128 | buf_end - buf); | |
129 | if (!t->bitstream_buf) | |
130 | return AVERROR(ENOMEM); | |
131 | t->bsdsp.bswap_buf(t->bitstream_buf, (const uint32_t *) buf, | |
132 | (buf_end - buf) / 4); | |
133 | init_get_bits(&s->gb, t->bitstream_buf, 8*(buf_end-buf)); | |
134 | ||
135 | s->last_dc[0] = s->last_dc[1] = s->last_dc[2] = 0; | |
136 | for (s->mb_y=0; s->mb_y<(avctx->height+15)/16; s->mb_y++) | |
137 | for (s->mb_x=0; s->mb_x<(avctx->width+15)/16; s->mb_x++) | |
138 | { | |
139 | if (tqi_decode_mb(s, t->block) < 0) | |
140 | goto end; | |
141 | tqi_idct_put(t, frame, t->block); | |
142 | } | |
143 | end: | |
144 | ||
145 | *got_frame = 1; | |
146 | return buf_size; | |
147 | } | |
148 | ||
149 | static av_cold int tqi_decode_end(AVCodecContext *avctx) | |
150 | { | |
151 | TqiContext *t = avctx->priv_data; | |
f6fa7814 | 152 | av_freep(&t->bitstream_buf); |
2ba45a60 DM |
153 | return 0; |
154 | } | |
155 | ||
156 | AVCodec ff_eatqi_decoder = { | |
157 | .name = "eatqi", | |
158 | .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TQI Video"), | |
159 | .type = AVMEDIA_TYPE_VIDEO, | |
160 | .id = AV_CODEC_ID_TQI, | |
161 | .priv_data_size = sizeof(TqiContext), | |
162 | .init = tqi_decode_init, | |
163 | .close = tqi_decode_end, | |
164 | .decode = tqi_decode_frame, | |
165 | .capabilities = CODEC_CAP_DR1, | |
166 | }; |