Mercurial > libavcodec.hg
annotate eamad.c @ 12266:48d6738904a9 libavcodec
Fix SPLATB_REG mess. Used to be a if/elseif/elseif/elseif spaghetti, so this
splits it into small optimization-specific macros which are selected for each
DSP function. The advantage of this approach is that the sse4 functions now
use the ssse3 codepath also without needing an explicit sse4 codepath.
author | rbultje |
---|---|
date | Sat, 24 Jul 2010 19:33:05 +0000 |
parents | 8b28e74de2c0 |
children | 914f484bb476 |
rev | line source |
---|---|
9848 | 1 /* |
2 * Electronic Arts Madcow Video Decoder | |
3 * Copyright (c) 2007-2009 Peter Ross | |
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 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
23 * @file |
9848 | 24 * Electronic Arts Madcow Video Decoder |
25 * by Peter Ross <pross@xvid.org> | |
26 * | |
27 * Technical details here: | |
28 * http://wiki.multimedia.cx/index.php?title=Electronic_Arts_MAD | |
29 */ | |
30 | |
31 #include "avcodec.h" | |
32 #include "get_bits.h" | |
33 #include "dsputil.h" | |
34 #include "aandcttab.h" | |
35 #include "mpeg12.h" | |
36 #include "mpeg12data.h" | |
37 | |
38 #define EA_PREAMBLE_SIZE 8 | |
39 #define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD i-frame */ | |
40 #define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD p-frame */ | |
41 #define MADe_TAG MKTAG('M', 'A', 'D', 'e') /* MAD lqp-frame */ | |
42 | |
43 typedef struct MadContext { | |
44 MpegEncContext s; | |
45 AVFrame frame; | |
46 AVFrame last_frame; | |
47 void *bitstream_buf; | |
48 unsigned int bitstream_buf_size; | |
11369 | 49 DECLARE_ALIGNED(16, DCTELEM, block)[64]; |
9848 | 50 } MadContext; |
51 | |
52 static void bswap16_buf(uint16_t *dst, const uint16_t *src, int count) | |
53 { | |
54 int i; | |
55 for (i=0; i<count; i++) | |
12129 | 56 dst[i] = av_bswap16(src[i]); |
9848 | 57 } |
58 | |
59 static av_cold int decode_init(AVCodecContext *avctx) | |
60 { | |
61 MadContext *t = avctx->priv_data; | |
62 MpegEncContext *s = &t->s; | |
63 s->avctx = avctx; | |
64 avctx->pix_fmt = PIX_FMT_YUV420P; | |
65 if (avctx->idct_algo == FF_IDCT_AUTO) | |
66 avctx->idct_algo = FF_IDCT_EA; | |
67 dsputil_init(&s->dsp, avctx); | |
68 ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable, ff_zigzag_direct); | |
69 ff_mpeg12_init_vlcs(); | |
70 return 0; | |
71 } | |
72 | |
73 static inline void comp(unsigned char *dst, int dst_stride, | |
74 unsigned char *src, int src_stride, int add) | |
75 { | |
76 int j, i; | |
77 for (j=0; j<8; j++) | |
78 for (i=0; i<8; i++) | |
79 dst[j*dst_stride + i] = av_clip_uint8(src[j*src_stride + i] + add); | |
80 } | |
81 | |
82 static inline void comp_block(MadContext *t, int mb_x, int mb_y, | |
83 int j, int mv_x, int mv_y, int add) | |
84 { | |
85 MpegEncContext *s = &t->s; | |
86 if (j < 4) { | |
87 comp(t->frame.data[0] + (mb_y*16 + ((j&2)<<2))*t->frame.linesize[0] + mb_x*16 + ((j&1)<<3), | |
88 t->frame.linesize[0], | |
89 t->last_frame.data[0] + (mb_y*16 + ((j&2)<<2) + mv_y)*t->last_frame.linesize[0] + mb_x*16 + ((j&1)<<3) + mv_x, | |
90 t->last_frame.linesize[0], add); | |
91 } else if (!(s->avctx->flags & CODEC_FLAG_GRAY)) { | |
92 int index = j - 3; | |
93 comp(t->frame.data[index] + (mb_y*8)*t->frame.linesize[index] + mb_x * 8, | |
94 t->frame.linesize[index], | |
95 t->last_frame.data[index] + (mb_y * 8 + (mv_y/2))*t->last_frame.linesize[index] + mb_x * 8 + (mv_x/2), | |
96 t->last_frame.linesize[index], add); | |
97 } | |
98 } | |
99 | |
100 static inline void idct_put(MadContext *t, DCTELEM *block, int mb_x, int mb_y, int j) | |
101 { | |
102 MpegEncContext *s = &t->s; | |
103 if (j < 4) { | |
104 s->dsp.idct_put( | |
105 t->frame.data[0] + (mb_y*16 + ((j&2)<<2))*t->frame.linesize[0] + mb_x*16 + ((j&1)<<3), | |
106 t->frame.linesize[0], block); | |
107 } else if (!(s->avctx->flags & CODEC_FLAG_GRAY)) { | |
108 int index = j - 3; | |
109 s->dsp.idct_put( | |
110 t->frame.data[index] + (mb_y*8)*t->frame.linesize[index] + mb_x*8, | |
111 t->frame.linesize[index], block); | |
112 } | |
113 } | |
114 | |
115 static inline void decode_block_intra(MadContext * t, DCTELEM * block) | |
116 { | |
117 MpegEncContext *s = &t->s; | |
118 int level, i, j, run; | |
119 RLTable *rl = &ff_rl_mpeg1; | |
120 const uint8_t *scantable = s->intra_scantable.permutated; | |
121 int16_t *quant_matrix = s->intra_matrix; | |
122 | |
123 block[0] = (128 + get_sbits(&s->gb, 8)) * quant_matrix[0]; | |
124 | |
125 /* The RL decoder is derived from mpeg1_decode_block_intra; | |
126 Escaped level and run values a decoded differently */ | |
9854
2428d32533f6
Initialise MAD decode_block_intra() loop iterator to zero.
pross
parents:
9848
diff
changeset
|
127 i = 0; |
9848 | 128 { |
129 OPEN_READER(re, &s->gb); | |
130 /* now quantify & encode AC coefficients */ | |
131 for (;;) { | |
132 UPDATE_CACHE(re, &s->gb); | |
133 GET_RL_VLC(level, run, re, &s->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2, 0); | |
134 | |
135 if (level == 127) { | |
136 break; | |
137 } else if (level != 0) { | |
138 i += run; | |
139 j = scantable[i]; | |
140 level = (level*quant_matrix[j]) >> 4; | |
141 level = (level-1)|1; | |
142 level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); | |
143 LAST_SKIP_BITS(re, &s->gb, 1); | |
144 } else { | |
145 /* escape */ | |
146 UPDATE_CACHE(re, &s->gb); | |
147 level = SHOW_SBITS(re, &s->gb, 10); SKIP_BITS(re, &s->gb, 10); | |
148 | |
149 UPDATE_CACHE(re, &s->gb); | |
150 run = SHOW_UBITS(re, &s->gb, 6)+1; LAST_SKIP_BITS(re, &s->gb, 6); | |
151 | |
152 i += run; | |
153 j = scantable[i]; | |
154 if (level < 0) { | |
155 level = -level; | |
156 level = (level*quant_matrix[j]) >> 4; | |
157 level = (level-1)|1; | |
158 level = -level; | |
159 } else { | |
160 level = (level*quant_matrix[j]) >> 4; | |
161 level = (level-1)|1; | |
162 } | |
163 } | |
164 if (i > 63) { | |
165 av_log(s->avctx, AV_LOG_ERROR, "ac-tex damaged at %d %d\n", s->mb_x, s->mb_y); | |
166 return; | |
167 } | |
168 | |
169 block[j] = level; | |
170 } | |
171 CLOSE_READER(re, &s->gb); | |
172 } | |
173 } | |
174 | |
175 static int decode_motion(GetBitContext *gb) | |
176 { | |
177 int value = 0; | |
178 if (get_bits1(gb)) { | |
179 if (get_bits1(gb)) | |
180 value = -17; | |
181 value += get_bits(gb, 4) + 1; | |
182 } | |
183 return value; | |
184 } | |
185 | |
186 static void decode_mb(MadContext *t, int inter) | |
187 { | |
188 MpegEncContext *s = &t->s; | |
189 int mv_map = 0; | |
190 int mv_x, mv_y; | |
191 int j; | |
192 | |
193 if (inter) { | |
194 int v = decode210(&s->gb); | |
195 if (v < 2) { | |
196 mv_map = v ? get_bits(&s->gb, 6) : 63; | |
197 mv_x = decode_motion(&s->gb); | |
198 mv_y = decode_motion(&s->gb); | |
199 } else { | |
200 mv_map = 0; | |
201 } | |
202 } | |
203 | |
204 for (j=0; j<6; j++) { | |
205 if (mv_map & (1<<j)) { // mv_x and mv_y are guarded by mv_map | |
206 int add = 2*decode_motion(&s->gb); | |
207 comp_block(t, s->mb_x, s->mb_y, j, mv_x, mv_y, add); | |
208 } else { | |
209 s->dsp.clear_block(t->block); | |
210 decode_block_intra(t, t->block); | |
211 idct_put(t, t->block, s->mb_x, s->mb_y, j); | |
212 } | |
213 } | |
214 } | |
215 | |
216 static void calc_intra_matrix(MadContext *t, int qscale) | |
217 { | |
218 MpegEncContext *s = &t->s; | |
219 int i; | |
220 | |
221 if (s->avctx->idct_algo == FF_IDCT_EA) { | |
222 s->intra_matrix[0] = (ff_inv_aanscales[0]*ff_mpeg1_default_intra_matrix[0]) >> 11; | |
223 for (i=1; i<64; i++) | |
224 s->intra_matrix[i] = (ff_inv_aanscales[i]*ff_mpeg1_default_intra_matrix[i]*qscale + 32) >> 10; | |
225 } else { | |
226 s->intra_matrix[0] = ff_mpeg1_default_intra_matrix[0]; | |
227 for (i=1; i<64; i++) | |
228 s->intra_matrix[i] = (ff_mpeg1_default_intra_matrix[i]*qscale) << 1; | |
229 } | |
230 } | |
231 | |
232 static int decode_frame(AVCodecContext *avctx, | |
233 void *data, int *data_size, | |
234 AVPacket *avpkt) | |
235 { | |
236 const uint8_t *buf = avpkt->data; | |
237 int buf_size = avpkt->size; | |
238 const uint8_t *buf_end = buf+buf_size; | |
239 MadContext *t = avctx->priv_data; | |
240 MpegEncContext *s = &t->s; | |
241 int chunk_type; | |
242 int inter; | |
243 | |
244 if (buf_size < 17) { | |
245 av_log(avctx, AV_LOG_ERROR, "Input buffer too small\n"); | |
246 *data_size = 0; | |
247 return -1; | |
248 } | |
249 | |
250 chunk_type = AV_RL32(&buf[0]); | |
251 inter = (chunk_type == MADm_TAG || chunk_type == MADe_TAG); | |
252 buf += 8; | |
253 | |
254 av_reduce(&avctx->time_base.num, &avctx->time_base.den, | |
255 AV_RL16(&buf[6]), 1000, 1<<30); | |
256 | |
257 s->width = AV_RL16(&buf[8]); | |
258 s->height = AV_RL16(&buf[10]); | |
259 calc_intra_matrix(t, buf[13]); | |
260 buf += 16; | |
261 | |
262 if (avctx->width != s->width || avctx->height != s->height) { | |
263 if (avcodec_check_dimensions(avctx, s->width, s->height) < 0) | |
264 return -1; | |
265 avcodec_set_dimensions(avctx, s->width, s->height); | |
266 if (t->frame.data[0]) | |
267 avctx->release_buffer(avctx, &t->frame); | |
268 } | |
269 | |
270 t->frame.reference = 1; | |
271 if (!t->frame.data[0]) { | |
272 if (avctx->get_buffer(avctx, &t->frame) < 0) { | |
273 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); | |
274 return -1; | |
275 } | |
276 } | |
277 | |
278 av_fast_malloc(&t->bitstream_buf, &t->bitstream_buf_size, (buf_end-buf) + FF_INPUT_BUFFER_PADDING_SIZE); | |
279 if (!t->bitstream_buf) | |
280 return AVERROR(ENOMEM); | |
281 bswap16_buf(t->bitstream_buf, (const uint16_t*)buf, (buf_end-buf)/2); | |
282 init_get_bits(&s->gb, t->bitstream_buf, 8*(buf_end-buf)); | |
283 | |
284 for (s->mb_y=0; s->mb_y < (avctx->height+15)/16; s->mb_y++) | |
285 for (s->mb_x=0; s->mb_x < (avctx->width +15)/16; s->mb_x++) | |
286 decode_mb(t, inter); | |
287 | |
288 *data_size = sizeof(AVFrame); | |
289 *(AVFrame*)data = t->frame; | |
290 | |
291 if (chunk_type != MADe_TAG) | |
292 FFSWAP(AVFrame, t->frame, t->last_frame); | |
293 | |
294 return buf_size; | |
295 } | |
296 | |
297 static av_cold int decode_end(AVCodecContext *avctx) | |
298 { | |
299 MadContext *t = avctx->priv_data; | |
300 if (t->frame.data[0]) | |
301 avctx->release_buffer(avctx, &t->frame); | |
302 if (t->last_frame.data[0]) | |
303 avctx->release_buffer(avctx, &t->last_frame); | |
304 av_free(t->bitstream_buf); | |
305 return 0; | |
306 } | |
307 | |
308 AVCodec eamad_decoder = { | |
309 "eamad", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11369
diff
changeset
|
310 AVMEDIA_TYPE_VIDEO, |
9848 | 311 CODEC_ID_MAD, |
312 sizeof(MadContext), | |
313 decode_init, | |
314 NULL, | |
315 decode_end, | |
316 decode_frame, | |
317 CODEC_CAP_DR1, | |
318 .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts Madcow Video") | |
319 }; |