Mercurial > libavcodec.hg
comparison mdec.c @ 1410:524c904a66b8 libavcodec
PSX MDEC decoder, based upon some code from Sebastian Jedruszkiewicz <elf at frogger dot rules dot pl>
note: completly untested, no demuxer yet
author | michaelni |
---|---|
date | Fri, 22 Aug 2003 14:59:04 +0000 |
parents | |
children | a7a9df478e46 |
comparison
equal
deleted
inserted
replaced
1409:62ea3b7d00f0 | 1410:524c904a66b8 |
---|---|
1 /* | |
2 * PSX MDEC codec | |
3 * Copyright (c) 2003 Michael Niedermayer | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 * | |
19 * based upon code from Sebastian Jedruszkiewicz <elf@frogger.rules.pl> | |
20 */ | |
21 | |
22 /** | |
23 * @file mdec.c | |
24 * PSX MDEC codec. | |
25 * This is very similar to intra only MPEG1. | |
26 */ | |
27 | |
28 #include "avcodec.h" | |
29 #include "dsputil.h" | |
30 #include "mpegvideo.h" | |
31 | |
32 //#undef NDEBUG | |
33 //#include <assert.h> | |
34 | |
35 typedef struct MDECContext{ | |
36 AVCodecContext *avctx; | |
37 DSPContext dsp; | |
38 AVFrame picture; | |
39 PutBitContext pb; | |
40 GetBitContext gb; | |
41 ScanTable scantable; | |
42 int version; | |
43 int qscale; | |
44 int last_dc[3]; | |
45 int mb_width; | |
46 int mb_height; | |
47 int mb_x, mb_y; | |
48 DCTELEM __align8 block[6][64]; | |
49 uint16_t __align8 intra_matrix[64]; | |
50 int __align8 q_intra_matrix[64]; | |
51 uint8_t *bitstream_buffer; | |
52 int bitstream_buffer_size; | |
53 int block_last_index[6]; | |
54 } MDECContext; | |
55 | |
56 //very similar to mpeg1 | |
57 static inline int mdec_decode_block_intra(MDECContext *a, DCTELEM *block, int n) | |
58 { | |
59 int level, diff, i, j, run; | |
60 int component; | |
61 RLTable *rl = &rl_mpeg1; | |
62 uint8_t * const scantable= a->scantable.permutated; | |
63 const uint16_t *quant_matrix= ff_mpeg1_default_intra_matrix; | |
64 const int qscale= a->qscale; | |
65 | |
66 /* DC coef */ | |
67 if(a->version==2){ | |
68 block[0]= get_sbits(&a->gb, 11); | |
69 }else{ | |
70 component = (n <= 3 ? 0 : n - 4 + 1); | |
71 diff = decode_dc(&a->gb, component); | |
72 if (diff >= 0xffff) | |
73 return -1; | |
74 a->last_dc[component]+= diff; | |
75 block[0] = a->last_dc[component]<<3; | |
76 } | |
77 | |
78 i = 0; | |
79 { | |
80 OPEN_READER(re, &a->gb); | |
81 /* now quantify & encode AC coefs */ | |
82 for(;;) { | |
83 UPDATE_CACHE(re, &a->gb); | |
84 GET_RL_VLC(level, run, re, &a->gb, rl->rl_vlc[0], TEX_VLC_BITS, 2); | |
85 | |
86 if(level == 127){ | |
87 break; | |
88 } else if(level != 0) { | |
89 i += run; | |
90 j = scantable[i]; | |
91 level= (level*qscale*quant_matrix[j])>>3; | |
92 level= (level-1)|1; | |
93 level = (level ^ SHOW_SBITS(re, &a->gb, 1)) - SHOW_SBITS(re, &a->gb, 1); | |
94 LAST_SKIP_BITS(re, &a->gb, 1); | |
95 } else { | |
96 /* escape */ | |
97 run = SHOW_UBITS(re, &a->gb, 6)+1; LAST_SKIP_BITS(re, &a->gb, 6); | |
98 UPDATE_CACHE(re, &a->gb); | |
99 level = SHOW_SBITS(re, &a->gb, 8); SKIP_BITS(re, &a->gb, 8); | |
100 if (level == -128) { | |
101 level = SHOW_UBITS(re, &a->gb, 8) - 256; LAST_SKIP_BITS(re, &a->gb, 8); | |
102 } else if (level == 0) { | |
103 level = SHOW_UBITS(re, &a->gb, 8) ; LAST_SKIP_BITS(re, &a->gb, 8); | |
104 } | |
105 i += run; | |
106 j = scantable[i]; | |
107 /* if(level<0){ | |
108 level= -level; | |
109 level= (level*qscale*quant_matrix[j])>>4; | |
110 level= (level-1)|1; | |
111 level= -level; | |
112 }else{*/ | |
113 level= (level*qscale*quant_matrix[j])>>4; | |
114 /* level= (level-1)|1; | |
115 }*/ | |
116 } | |
117 if (i > 63){ | |
118 fprintf(stderr, "ac-tex damaged at %d %d\n", a->mb_x, a->mb_y); | |
119 return -1; | |
120 } | |
121 | |
122 block[j] = level; | |
123 } | |
124 CLOSE_READER(re, &a->gb); | |
125 } | |
126 a->block_last_index[n] = i; | |
127 return 0; | |
128 } | |
129 | |
130 static inline int decode_mb(MDECContext *a, DCTELEM block[6][64]){ | |
131 int i; | |
132 | |
133 a->dsp.clear_blocks(block[0]); | |
134 | |
135 for(i=5; i>=0; i--){ | |
136 if( mdec_decode_block_intra(a, block[i], i) < 0) | |
137 return -1; | |
138 } | |
139 return 0; | |
140 } | |
141 | |
142 static inline void idct_put(MDECContext *a, int mb_x, int mb_y){ | |
143 DCTELEM (*block)[64]= a->block; | |
144 int linesize= a->picture.linesize[0]; | |
145 | |
146 uint8_t *dest_y = a->picture.data[0] + (mb_y * 16* linesize ) + mb_x * 16; | |
147 uint8_t *dest_cb = a->picture.data[1] + (mb_y * 8 * a->picture.linesize[1]) + mb_x * 8; | |
148 uint8_t *dest_cr = a->picture.data[2] + (mb_y * 8 * a->picture.linesize[2]) + mb_x * 8; | |
149 | |
150 a->dsp.idct_put(dest_y , linesize, block[0]); | |
151 a->dsp.idct_put(dest_y + 8, linesize, block[1]); | |
152 a->dsp.idct_put(dest_y + 8*linesize , linesize, block[2]); | |
153 a->dsp.idct_put(dest_y + 8*linesize + 8, linesize, block[3]); | |
154 | |
155 if(!(a->avctx->flags&CODEC_FLAG_GRAY)){ | |
156 a->dsp.idct_put(dest_cb, a->picture.linesize[1], block[4]); | |
157 a->dsp.idct_put(dest_cr, a->picture.linesize[2], block[5]); | |
158 } | |
159 } | |
160 | |
161 static int decode_frame(AVCodecContext *avctx, | |
162 void *data, int *data_size, | |
163 uint8_t *buf, int buf_size) | |
164 { | |
165 MDECContext * const a = avctx->priv_data; | |
166 AVFrame *picture = data; | |
167 AVFrame * const p= (AVFrame*)&a->picture; | |
168 int i; | |
169 | |
170 *data_size = 0; | |
171 | |
172 /* special case for last picture */ | |
173 if (buf_size == 0) { | |
174 return 0; | |
175 } | |
176 | |
177 if(p->data[0]) | |
178 avctx->release_buffer(avctx, p); | |
179 | |
180 p->reference= 0; | |
181 if(avctx->get_buffer(avctx, p) < 0){ | |
182 fprintf(stderr, "get_buffer() failed\n"); | |
183 return -1; | |
184 } | |
185 p->pict_type= I_TYPE; | |
186 p->key_frame= 1; | |
187 a->last_dc[0]= | |
188 a->last_dc[1]= | |
189 a->last_dc[2]= 0; | |
190 | |
191 a->bitstream_buffer= av_fast_realloc(a->bitstream_buffer, &a->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); | |
192 for(i=0; 2*i<buf_size; i+=2){ | |
193 ((uint16_t*)a->bitstream_buffer)[i] = ((uint16_t*)buf)[i+1]; | |
194 ((uint16_t*)a->bitstream_buffer)[i+1]= ((uint16_t*)buf)[i ]; | |
195 } | |
196 // a->dsp.bswap_buf((uint32_t*)a->bitstream_buffer, (uint32_t*)buf, buf_size/4); | |
197 init_get_bits(&a->gb, a->bitstream_buffer, buf_size*8); | |
198 | |
199 a->qscale= get_bits(&a->gb, 16); | |
200 a->version= get_bits(&a->gb, 16); | |
201 skip_bits(&a->gb, 8*8); | |
202 | |
203 printf("qscale:%d, version:%d\n", a->qscale, a->version); | |
204 | |
205 for(a->mb_y=0; a->mb_y<a->mb_height; a->mb_y++){ | |
206 for(a->mb_x=0; a->mb_x<a->mb_width; a->mb_x++){ | |
207 if( decode_mb(a, a->block) <0) | |
208 return -1; | |
209 | |
210 idct_put(a, a->mb_x, a->mb_y); | |
211 } | |
212 } | |
213 | |
214 #if 0 | |
215 int i; | |
216 printf("%d %d\n", 8*buf_size, get_bits_count(&a->gb)); | |
217 for(i=get_bits_count(&a->gb); i<8*buf_size; i++){ | |
218 printf("%d", get_bits1(&a->gb)); | |
219 } | |
220 | |
221 for(i=0; i<s->avctx->extradata_size; i++){ | |
222 printf("%c\n", ((uint8_t*)s->avctx->extradata)[i]); | |
223 } | |
224 #endif | |
225 | |
226 // p->quality= (32 + a->inv_qscale/2)/a->inv_qscale; | |
227 // memset(p->qscale_table, p->quality, p->qstride*a->mb_height); | |
228 | |
229 *picture= *(AVFrame*)&a->picture; | |
230 *data_size = sizeof(AVPicture); | |
231 | |
232 emms_c(); | |
233 | |
234 return (get_bits_count(&a->gb)+31)/32*4; | |
235 } | |
236 | |
237 static void mdec_common_init(AVCodecContext *avctx){ | |
238 MDECContext * const a = avctx->priv_data; | |
239 | |
240 dsputil_init(&a->dsp, avctx); | |
241 | |
242 a->mb_width = (avctx->width + 15) / 16; | |
243 a->mb_height = (avctx->height + 15) / 16; | |
244 | |
245 avctx->coded_frame= (AVFrame*)&a->picture; | |
246 a->avctx= avctx; | |
247 } | |
248 | |
249 static int decode_init(AVCodecContext *avctx){ | |
250 MDECContext * const a = avctx->priv_data; | |
251 AVFrame *p= (AVFrame*)&a->picture; | |
252 int i; | |
253 | |
254 mdec_common_init(avctx); | |
255 init_vlcs(); | |
256 ff_init_scantable(a->dsp.idct_permutation, &a->scantable, ff_zigzag_direct); | |
257 /* | |
258 for(i=0; i<64; i++){ | |
259 int index= ff_zigzag_direct[i]; | |
260 a->intra_matrix[i]= 64*ff_mpeg1_default_intra_matrix[index] / a->inv_qscale; | |
261 } | |
262 */ | |
263 p->qstride= a->mb_width; | |
264 p->qscale_table= av_mallocz( p->qstride * a->mb_height); | |
265 | |
266 return 0; | |
267 } | |
268 | |
269 static int decode_end(AVCodecContext *avctx){ | |
270 MDECContext * const a = avctx->priv_data; | |
271 | |
272 av_freep(&a->bitstream_buffer); | |
273 av_freep(&a->picture.qscale_table); | |
274 a->bitstream_buffer_size=0; | |
275 | |
276 avcodec_default_free_buffers(avctx); | |
277 | |
278 return 0; | |
279 } | |
280 | |
281 AVCodec mdec_decoder = { | |
282 "mdec", | |
283 CODEC_TYPE_VIDEO, | |
284 CODEC_ID_MDEC, | |
285 sizeof(MDECContext), | |
286 decode_init, | |
287 NULL, | |
288 decode_end, | |
289 decode_frame, | |
290 CODEC_CAP_DR1, | |
291 }; | |
292 |