Mercurial > libavcodec.hg
annotate intrax8.c @ 9830:bd0879f752e6 libavcodec
Express the H.264 parser dependency on the golomb code in configure instead of
in the Makefile as it is done for all other parts that depend on golomb.
author | diego |
---|---|
date | Tue, 09 Jun 2009 20:29:52 +0000 |
parents | 0dce4fe6e6f3 |
children | 64ee90bc6c31 |
rev | line source |
---|---|
5887 | 1 /* |
2 * This file is part of FFmpeg. | |
3 * | |
4 * FFmpeg is free software; you can redistribute it and/or | |
5 * modify it under the terms of the GNU Lesser General Public | |
6 * License as published by the Free Software Foundation; either | |
7 * version 2.1 of the License, or (at your option) any later version. | |
8 * | |
9 * FFmpeg is distributed in the hope that it will be useful, | |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * Lesser General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU Lesser General Public | |
15 * License along with FFmpeg; if not, write to the Free Software | |
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
17 */ | |
18 | |
19 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8527
diff
changeset
|
20 * @file libavcodec/intrax8.c |
5906 | 21 * @brief IntraX8 (J-Frame) subdecoder, used by WMV2 and VC-1 |
5887 | 22 */ |
23 | |
24 #include "avcodec.h" | |
9428 | 25 #include "get_bits.h" |
5887 | 26 #include "mpegvideo.h" |
27 #include "msmpeg4data.h" | |
28 #include "intrax8huf.h" | |
29 #include "intrax8.h" | |
30 | |
31 #define MAX_TABLE_DEPTH(table_bits, max_bits) ((max_bits+table_bits-1)/table_bits) | |
32 | |
33 #define DC_VLC_BITS 9 | |
34 #define AC_VLC_BITS 9 | |
35 #define OR_VLC_BITS 7 | |
36 | |
37 #define DC_VLC_MTD MAX_TABLE_DEPTH(DC_VLC_BITS, MAX_DC_VLC_BITS) | |
38 #define AC_VLC_MTD MAX_TABLE_DEPTH(AC_VLC_BITS, MAX_AC_VLC_BITS) | |
39 #define OR_VLC_MTD MAX_TABLE_DEPTH(OR_VLC_BITS, MAX_OR_VLC_BITS) | |
40 | |
41 static VLC j_ac_vlc[2][2][8]; //[quant<13],[intra/inter],[select] | |
42 static VLC j_dc_vlc[2][8]; //[quant], [select] | |
43 static VLC j_orient_vlc[2][4]; //[quant], [select] | |
44 | |
8737
eeca2fc122f8
Add av_cold attributes to *_init and *_end functions.
alexc
parents:
8718
diff
changeset
|
45 static av_cold void x8_vlc_init(void){ |
5887 | 46 int i; |
47 | |
48 #define init_ac_vlc(dst,src) \ | |
49 init_vlc(&dst, \ | |
50 AC_VLC_BITS,77, \ | |
51 &src[1],4,2, \ | |
52 &src[0],4,2, \ | |
9393 | 53 INIT_VLC_USE_STATIC) |
5887 | 54 //set ac tables |
55 for(i=0;i<8;i++){ | |
5903 | 56 init_ac_vlc( j_ac_vlc[0][0][i], x8_ac0_highquant_table[i][0] ); |
57 init_ac_vlc( j_ac_vlc[0][1][i], x8_ac1_highquant_table[i][0] ); | |
58 init_ac_vlc( j_ac_vlc[1][0][i], x8_ac0_lowquant_table [i][0] ); | |
59 init_ac_vlc( j_ac_vlc[1][1][i], x8_ac1_lowquant_table [i][0] ); | |
5887 | 60 } |
61 #undef init_ac_vlc | |
62 | |
63 //set dc tables | |
64 #define init_dc_vlc(dst,src) \ | |
65 init_vlc(&dst, \ | |
66 DC_VLC_BITS,34, \ | |
67 &src[1],4,2, \ | |
68 &src[0],4,2, \ | |
9401 | 69 INIT_VLC_USE_STATIC); |
5887 | 70 for(i=0;i<8;i++){ |
5903 | 71 init_dc_vlc( j_dc_vlc[0][i], x8_dc_highquant_table[i][0]); |
72 init_dc_vlc( j_dc_vlc[1][i], x8_dc_lowquant_table [i][0]); | |
5887 | 73 } |
74 #undef init_dc_vlc | |
75 | |
76 //set orient tables | |
77 #define init_or_vlc(dst,src) \ | |
78 init_vlc(&dst, \ | |
79 OR_VLC_BITS,12, \ | |
80 &src[1],4,2, \ | |
81 &src[0],4,2, \ | |
9393 | 82 INIT_VLC_USE_STATIC); |
5887 | 83 for(i=0;i<2;i++){ |
5903 | 84 init_or_vlc( j_orient_vlc[0][i], x8_orient_highquant_table[i][0]); |
5887 | 85 } |
86 for(i=0;i<4;i++){ | |
5903 | 87 init_or_vlc( j_orient_vlc[1][i], x8_orient_lowquant_table [i][0]) |
5887 | 88 } |
89 } | |
90 #undef init_or_vlc | |
91 | |
5898 | 92 static void x8_reset_vlc_tables(IntraX8Context * w){ |
5887 | 93 memset(w->j_dc_vlc,0,sizeof(w->j_dc_vlc)); |
94 memset(w->j_ac_vlc,0,sizeof(w->j_ac_vlc)); | |
95 w->j_orient_vlc=NULL; | |
96 } | |
97 | |
98 static inline void x8_select_ac_table(IntraX8Context * const w , int mode){ | |
99 MpegEncContext * const s= w->s; | |
100 int table_index; | |
101 | |
102 assert(mode<4); | |
103 | |
104 if( w->j_ac_vlc[mode] ) return; | |
105 | |
106 table_index = get_bits(&s->gb, 3); | |
107 w->j_ac_vlc[mode] = &j_ac_vlc[w->quant<13][mode>>1][table_index];//2 modes use same tables | |
108 assert(w->j_ac_vlc[mode]); | |
109 } | |
110 | |
111 static inline int x8_get_orient_vlc(IntraX8Context * w){ | |
112 MpegEncContext * const s= w->s; | |
113 int table_index; | |
114 | |
115 if(!w->j_orient_vlc ){ | |
116 table_index = get_bits(&s->gb, 1+(w->quant<13) ); | |
117 w->j_orient_vlc = &j_orient_vlc[w->quant<13][table_index]; | |
118 } | |
119 assert(w->j_orient_vlc); | |
120 assert(w->j_orient_vlc->table); | |
121 | |
122 return get_vlc2(&s->gb, w->j_orient_vlc->table, OR_VLC_BITS, OR_VLC_MTD); | |
123 } | |
124 | |
125 #define extra_bits(eb) (eb) | |
126 #define extra_run (0xFF<<8) | |
127 #define extra_level (0x00<<8) | |
128 #define run_offset(r) ((r)<<16) | |
129 #define level_offset(l) ((l)<<24) | |
130 static const uint32_t ac_decode_table[]={ | |
131 /*46*/ extra_bits(3) | extra_run | run_offset(16) | level_offset( 0), | |
132 /*47*/ extra_bits(3) | extra_run | run_offset(24) | level_offset( 0), | |
133 /*48*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), | |
134 /*49*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), | |
135 | |
136 /*50*/ extra_bits(5) | extra_run | run_offset(32) | level_offset( 0), | |
137 /*51*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), | |
138 | |
139 /*52*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), | |
140 /*53*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 8), | |
141 /*54*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset(12), | |
142 /*55*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(16), | |
143 /*56*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset(24), | |
144 | |
145 /*57*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), | |
146 /*58*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), | |
147 | |
148 /*59*/ extra_bits(2) | extra_run | run_offset(16) | level_offset( 0), | |
149 /*60*/ extra_bits(2) | extra_run | run_offset(20) | level_offset( 0), | |
150 /*61*/ extra_bits(2) | extra_run | run_offset(24) | level_offset( 0), | |
151 /*62*/ extra_bits(2) | extra_run | run_offset(28) | level_offset( 0), | |
152 /*63*/ extra_bits(4) | extra_run | run_offset(32) | level_offset( 0), | |
153 /*64*/ extra_bits(4) | extra_run | run_offset(48) | level_offset( 0), | |
154 | |
155 /*65*/ extra_bits(2) | extra_run | run_offset( 4) | level_offset( 1), | |
156 /*66*/ extra_bits(3) | extra_run | run_offset( 8) | level_offset( 1), | |
157 /*67*/ extra_bits(4) | extra_run | run_offset(16) | level_offset( 1), | |
158 | |
159 /*68*/ extra_bits(2) | extra_level | run_offset( 0) | level_offset( 4), | |
160 /*69*/ extra_bits(3) | extra_level | run_offset( 0) | level_offset( 8), | |
161 /*70*/ extra_bits(4) | extra_level | run_offset( 0) | level_offset(16), | |
162 | |
163 /*71*/ extra_bits(2) | extra_level | run_offset( 1) | level_offset( 3), | |
164 /*72*/ extra_bits(3) | extra_level | run_offset( 1) | level_offset( 7), | |
165 }; | |
166 //extra_bits = 3bits; extra_run/level = 1 bit; run_offset = 6bits; level_offset = 5 bits; | |
167 #undef extra_bits | |
168 #undef extra_run | |
169 #undef extra_level | |
170 #undef run_offset | |
171 #undef level_offset | |
172 | |
173 static void x8_get_ac_rlf(IntraX8Context * const w, const int mode, | |
174 int * const run, int * const level, int * const final){ | |
175 MpegEncContext * const s= w->s; | |
176 int i,e; | |
177 | |
178 // x8_select_ac_table(w,mode); | |
179 i = get_vlc2(&s->gb, w->j_ac_vlc[mode]->table, AC_VLC_BITS, AC_VLC_MTD); | |
180 | |
181 if(i<46){ //[0-45] | |
182 int t,l; | |
183 if(i<0){ | |
184 (*level)=(*final)=//prevent 'may be used unilitialized' | |
185 (*run)=64;//this would cause error exit in the ac loop | |
186 return; | |
187 } | |
188 | |
189 (*final) = t = (i>22); | |
190 i-=23*t; | |
191 /* | |
192 i== 0-15 r=0-15 l=0 ;r=i& %01111 | |
193 i==16-19 r=0-3 l=1 ;r=i& %00011 | |
194 i==20-21 r=0-1 l=2 ;r=i& %00001 | |
195 i==22 r=0 l=3 ;r=i& %00000 | |
196 l=lut_l[i/2]={0,0,0,0,0,0,0,0,1,1,2,3}[i>>1];// 11 10'01 01'00 00'00 00'00 00'00 00 => 0xE50000 | |
5906 | 197 t=lut_mask[l]={0x0f,0x03,0x01,0x00}[l]; as i<256 the higher bits do not matter */ |
5887 | 198 l=(0xE50000>>(i&(0x1E)))&3;/*0x1E or (~1) or ((i>>1)<<1)*/ |
199 t=(0x01030F>>(l<<3)); | |
200 | |
201 (*run) = i&t; | |
202 (*level) = l; | |
203 }else if(i<73){//[46-72] | |
204 uint32_t sm; | |
205 uint32_t mask; | |
206 | |
207 i-=46; | |
208 sm=ac_decode_table[i]; | |
209 | |
210 e=get_bits(&s->gb,sm&0xF);sm>>=8;//3bits | |
211 mask=sm&0xff;sm>>=8; //1bit | |
212 | |
213 (*run) =(sm&0xff) + (e&( mask));//6bits | |
214 (*level)=(sm>>8) + (e&(~mask));//5bits | |
215 (*final)=i>(58-46); | |
216 }else if(i<75){//[73-74] | |
217 static const uint8_t crazy_mix_runlevel[32]={ | |
218 0x22,0x32,0x33,0x53,0x23,0x42,0x43,0x63, | |
219 0x24,0x52,0x34,0x73,0x25,0x62,0x44,0x83, | |
220 0x26,0x72,0x35,0x54,0x27,0x82,0x45,0x64, | |
221 0x28,0x92,0x36,0x74,0x29,0xa2,0x46,0x84}; | |
222 | |
223 (*final)=!(i&1); | |
224 e=get_bits(&s->gb,5);//get the extra bits | |
225 (*run) =crazy_mix_runlevel[e]>>4; | |
226 (*level)=crazy_mix_runlevel[e]&0x0F; | |
227 }else{ | |
228 (*level)=get_bits( &s->gb, 7-3*(i&1)); | |
229 (*run) =get_bits( &s->gb, 6); | |
230 (*final)=get_bits1(&s->gb); | |
231 } | |
232 return; | |
233 } | |
234 | |
235 //static const uint8_t dc_extra_sbits[] ={0, 1,1, 1,1, 2,2, 3,3, 4,4, 5,5, 6,6, 7,7 }; | |
236 static const uint8_t dc_index_offset[] ={ 0, 1,2, 3,4, 5,7, 9,13, 17,25, 33,49, 65,97, 129,193}; | |
237 | |
238 static int x8_get_dc_rlf(IntraX8Context * const w,int const mode, int * const level, int * const final){ | |
239 MpegEncContext * const s= w->s; | |
240 int i,e,c; | |
241 | |
242 assert(mode<3); | |
243 if( !w->j_dc_vlc[mode] ) { | |
244 int table_index; | |
245 table_index = get_bits(&s->gb, 3); | |
246 //4 modes, same table | |
247 w->j_dc_vlc[mode]= &j_dc_vlc[w->quant<13][table_index]; | |
248 } | |
249 assert(w->j_dc_vlc); | |
250 assert(w->j_dc_vlc[mode]->table); | |
251 | |
252 i=get_vlc2(&s->gb, w->j_dc_vlc[mode]->table, DC_VLC_BITS, DC_VLC_MTD); | |
253 | |
254 /*(i>=17) {i-=17;final=1;}*/ | |
255 c= i>16; | |
256 (*final)=c; | |
257 i-=17*c; | |
258 | |
259 if(i<=0){ | |
260 (*level)=0; | |
261 return -i; | |
262 } | |
263 c=(i+1)>>1;//hackish way to calculate dc_extra_sbits[] | |
264 c-=c>1; | |
265 | |
266 e=get_bits(&s->gb,c);//get the extra bits | |
267 i=dc_index_offset[i]+(e>>1); | |
268 | |
269 e= -(e & 1);//0,0xffffff | |
270 (*level)= (i ^ e) - e;// (i^0)-0 , (i^0xff)-(-1) | |
271 return 0; | |
272 } | |
273 //end of huffman | |
274 | |
275 static int x8_setup_spatial_predictor(IntraX8Context * const w, const int chroma){ | |
276 MpegEncContext * const s= w->s; | |
277 int range; | |
278 int sum; | |
279 int quant; | |
280 | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
281 s->dsp.x8_setup_spatial_compensation(s->dest[chroma], s->edge_emu_buffer, |
5887 | 282 s->current_picture.linesize[chroma>0], |
283 &range, &sum, w->edges); | |
284 if(chroma){ | |
285 w->orient=w->chroma_orient; | |
286 quant=w->quant_dc_chroma; | |
287 }else{ | |
288 quant=w->quant; | |
289 } | |
290 | |
291 w->flat_dc=0; | |
292 if(range < quant || range < 3){ | |
293 w->orient=0; | |
5906 | 294 if(range < 3){//yep you read right, a +-1 idct error may break decoding! |
5887 | 295 w->flat_dc=1; |
296 sum+=9; | |
297 w->predicted_dc = (sum*6899)>>17;//((1<<17)+9)/(8+8+1+2)=6899 | |
298 } | |
299 } | |
300 if(chroma) | |
301 return 0; | |
302 | |
303 assert(w->orient < 3); | |
304 if(range < 2*w->quant){ | |
305 if( (w->edges&3) == 0){ | |
306 if(w->orient==1) w->orient=11; | |
307 if(w->orient==2) w->orient=10; | |
308 }else{ | |
309 w->orient=0; | |
310 } | |
311 w->raw_orient=0; | |
312 }else{ | |
313 static const uint8_t prediction_table[3][12]={ | |
314 {0,8,4, 10,11, 2,6,9,1,3,5,7}, | |
315 {4,0,8, 11,10, 3,5,2,6,9,1,7}, | |
316 {8,0,4, 10,11, 1,7,2,6,9,3,5} | |
317 }; | |
318 w->raw_orient=x8_get_orient_vlc(w); | |
319 if(w->raw_orient<0) return -1; | |
320 assert(w->raw_orient < 12 ); | |
321 assert(w->orient<3); | |
322 w->orient=prediction_table[w->orient][w->raw_orient]; | |
323 } | |
324 return 0; | |
325 } | |
326 | |
327 static void x8_update_predictions(IntraX8Context * const w, const int orient, const int est_run ){ | |
328 MpegEncContext * const s= w->s; | |
329 | |
330 w->prediction_table[s->mb_x*2+(s->mb_y&1)] = (est_run<<2) + 1*(orient==4) + 2*(orient==8); | |
331 /* | |
332 y=2n+0 ->//0 2 4 | |
333 y=2n+1 ->//1 3 5 | |
334 */ | |
335 } | |
336 static void x8_get_prediction_chroma(IntraX8Context * const w){ | |
337 MpegEncContext * const s= w->s; | |
338 | |
339 w->edges = 1*( !(s->mb_x>>1) ); | |
340 w->edges|= 2*( !(s->mb_y>>1) ); | |
341 w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) );//mb_x for chroma would always be odd | |
342 | |
343 w->raw_orient=0; | |
344 if(w->edges&3){//lut_co[8]={inv,4,8,8, inv,4,8,8}<- =>{1,1,0,0;1,1,0,0} => 0xCC | |
345 w->chroma_orient=4<<((0xCC>>w->edges)&1); | |
346 return; | |
347 } | |
348 w->chroma_orient = (w->prediction_table[2*s->mb_x-2] & 0x03)<<2;//block[x-1][y|1-1)] | |
349 } | |
350 | |
351 static void x8_get_prediction(IntraX8Context * const w){ | |
352 MpegEncContext * const s= w->s; | |
353 int a,b,c,i; | |
354 | |
355 w->edges = 1*( !s->mb_x ); | |
356 w->edges|= 2*( !s->mb_y ); | |
357 w->edges|= 4*( s->mb_x >= (2*s->mb_width-1) ); | |
358 | |
359 switch(w->edges&3){ | |
360 case 0: | |
361 break; | |
362 case 1: | |
363 //take the one from the above block[0][y-1] | |
364 w->est_run = w->prediction_table[!(s->mb_y&1)]>>2; | |
365 w->orient = 1; | |
366 return; | |
367 case 2: | |
368 //take the one from the previous block[x-1][0] | |
369 w->est_run = w->prediction_table[2*s->mb_x-2]>>2; | |
370 w->orient = 2; | |
371 return; | |
372 case 3: | |
373 w->est_run = 16; | |
374 w->orient = 0; | |
375 return; | |
376 } | |
5906 | 377 //no edge cases |
5887 | 378 b= w->prediction_table[2*s->mb_x + !(s->mb_y&1) ];//block[x ][y-1] |
379 a= w->prediction_table[2*s->mb_x-2 + (s->mb_y&1) ];//block[x-1][y ] | |
380 c= w->prediction_table[2*s->mb_x-2 + !(s->mb_y&1) ];//block[x-1][y-1] | |
381 | |
382 w->est_run = FFMIN(b,a); | |
5906 | 383 /* This condition has nothing to do with w->edges, even if it looks |
384 similar it would trigger if e.g. x=3;y=2; | |
385 I guess somebody wrote something wrong and it became standard. */ | |
5887 | 386 if( (s->mb_x & s->mb_y) != 0 ) w->est_run=FFMIN(c,w->est_run); |
387 w->est_run>>=2; | |
388 | |
389 a&=3; | |
390 b&=3; | |
391 c&=3; | |
392 | |
393 i=( 0xFFEAF4C4>>(2*b+8*a) )&3; | |
394 if(i!=3) w->orient=i; | |
395 else w->orient=( 0xFFEAD8>>(2*c+8*(w->quant>12)) )&3; | |
396 /* | |
397 lut1[b][a]={ | |
398 ->{0, 1, 0, pad}, | |
399 {0, 1, X, pad}, | |
400 {2, 2, 2, pad}} | |
401 pad 2 2 2; pad X 1 0; pad 0 1 0 <- | |
402 -> 11 10 '10 10 '11 11'01 00 '11 00'01 00=>0xEAF4C4 | |
403 | |
404 lut2[q>12][c]={ | |
405 ->{0,2,1,pad}, | |
406 {2,2,2,pad}} | |
407 pad 2 2 2; pad 1 2 0 <- | |
408 -> 11 10'10 10 '11 01'10 00=>0xEAD8 | |
409 */ | |
410 } | |
411 | |
412 | |
413 static void x8_ac_compensation(IntraX8Context * const w, int const direction, int const dc_level){ | |
414 MpegEncContext * const s= w->s; | |
415 int t; | |
416 #define B(x,y) s->block[0][s->dsp.idct_permutation[(x)+(y)*8]] | |
417 #define T(x) ((x) * dc_level + 0x8000) >> 16; | |
418 switch(direction){ | |
419 case 0: | |
420 t = T(3811);//h | |
421 B(1,0) -= t; | |
422 B(0,1) -= t; | |
423 | |
424 t = T(487);//e | |
425 B(2,0) -= t; | |
426 B(0,2) -= t; | |
427 | |
428 t = T(506);//f | |
429 B(3,0) -= t; | |
430 B(0,3) -= t; | |
431 | |
432 t = T(135);//c | |
433 B(4,0) -= t; | |
434 B(0,4) -= t; | |
435 B(2,1) += t; | |
436 B(1,2) += t; | |
437 B(3,1) += t; | |
438 B(1,3) += t; | |
439 | |
440 t = T(173);//d | |
441 B(5,0) -= t; | |
442 B(0,5) -= t; | |
443 | |
444 t = T(61);//b | |
445 B(6,0) -= t; | |
446 B(0,6) -= t; | |
447 B(5,1) += t; | |
448 B(1,5) += t; | |
449 | |
450 t = T(42); //a | |
451 B(7,0) -= t; | |
452 B(0,7) -= t; | |
453 B(4,1) += t; | |
454 B(1,4) += t; | |
455 B(4,4) += t; | |
456 | |
457 t = T(1084);//g | |
458 B(1,1) += t; | |
459 | |
460 s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); | |
461 break; | |
462 case 1: | |
463 B(0,1) -= T(6269); | |
464 B(0,3) -= T( 708); | |
465 B(0,5) -= T( 172); | |
466 B(0,7) -= T( 73); | |
467 | |
468 s->block_last_index[0] = FFMAX(s->block_last_index[0], 7*8); | |
469 break; | |
470 case 2: | |
471 B(1,0) -= T(6269); | |
472 B(3,0) -= T( 708); | |
473 B(5,0) -= T( 172); | |
474 B(7,0) -= T( 73); | |
475 | |
476 s->block_last_index[0] = FFMAX(s->block_last_index[0], 7); | |
477 break; | |
478 } | |
479 #undef B | |
480 #undef T | |
481 } | |
482 | |
483 static void dsp_x8_put_solidcolor(uint8_t const pix, uint8_t * dst, int const linesize){ | |
484 int k; | |
485 for(k=0;k<8;k++){ | |
486 memset(dst,pix,8); | |
487 dst+=linesize; | |
488 } | |
489 } | |
490 | |
491 static const int16_t quant_table[64] = { | |
492 256, 256, 256, 256, 256, 256, 259, 262, | |
493 265, 269, 272, 275, 278, 282, 285, 288, | |
494 292, 295, 299, 303, 306, 310, 314, 317, | |
495 321, 325, 329, 333, 337, 341, 345, 349, | |
496 353, 358, 362, 366, 371, 375, 379, 384, | |
497 389, 393, 398, 403, 408, 413, 417, 422, | |
498 428, 433, 438, 443, 448, 454, 459, 465, | |
499 470, 476, 482, 488, 493, 499, 505, 511 | |
500 }; | |
501 | |
502 static int x8_decode_intra_mb(IntraX8Context* const w, const int chroma){ | |
5900 | 503 MpegEncContext * const s= w->s; |
5887 | 504 |
505 uint8_t * scantable; | |
506 int final,run,level; | |
507 int ac_mode,dc_mode,est_run,dc_level; | |
508 int pos,n; | |
509 int zeros_only; | |
510 int use_quant_matrix; | |
511 int sign; | |
512 | |
513 assert(w->orient<12); | |
8288 | 514 s->dsp.clear_block(s->block[0]); |
5887 | 515 |
516 if(chroma){ | |
517 dc_mode=2; | |
518 }else{ | |
519 dc_mode=!!w->est_run;//0,1 | |
520 } | |
521 | |
522 if(x8_get_dc_rlf(w, dc_mode, &dc_level, &final)) return -1; | |
523 n=0; | |
524 zeros_only=0; | |
525 if(!final){//decode ac | |
526 use_quant_matrix=w->use_quant_matrix; | |
527 if(chroma){ | |
528 ac_mode = 1; | |
529 est_run = 64;//not used | |
530 }else{ | |
531 if (w->raw_orient < 3){ | |
532 use_quant_matrix = 0; | |
533 } | |
534 if(w->raw_orient > 4){ | |
535 ac_mode = 0; | |
536 est_run = 64; | |
537 }else{ | |
538 if(w->est_run > 1){ | |
539 ac_mode = 2; | |
540 est_run=w->est_run; | |
541 }else{ | |
542 ac_mode = 3; | |
543 est_run = 64; | |
544 } | |
545 } | |
546 } | |
547 x8_select_ac_table(w,ac_mode); | |
548 /*scantable_selector[12]={0,2,0,1,1,1,0,2,2,0,1,2};<- | |
549 -> 10'01' 00'10' 10'00' 01'01' 01'00' 10'00 =>0x928548 */ | |
550 scantable = w->scantable[ (0x928548>>(2*w->orient))&3 ].permutated; | |
551 pos=0; | |
552 do { | |
553 n++; | |
554 if( n >= est_run ){ | |
555 ac_mode=3; | |
556 x8_select_ac_table(w,3); | |
557 } | |
558 | |
559 x8_get_ac_rlf(w,ac_mode,&run,&level,&final); | |
560 | |
561 pos+=run+1; | |
562 if(pos>63){ | |
563 //this also handles vlc error in x8_get_ac_rlf | |
564 return -1; | |
565 } | |
566 level= (level+1) * w->dquant; | |
567 level+= w->qsum; | |
568 | |
569 sign = - get_bits1(&s->gb); | |
570 level = (level ^ sign) - sign; | |
571 | |
572 if(use_quant_matrix){ | |
573 level = (level*quant_table[pos])>>8; | |
574 } | |
575 s->block[0][ scantable[pos] ]=level; | |
576 }while(!final); | |
577 | |
578 s->block_last_index[0]=pos; | |
579 }else{//DC only | |
580 s->block_last_index[0]=0; | |
581 if(w->flat_dc && ((unsigned)(dc_level+1)) < 3){//[-1;1] | |
582 int32_t divide_quant= !chroma ? w->divide_quant_dc_luma: | |
583 w->divide_quant_dc_chroma; | |
584 int32_t dc_quant = !chroma ? w->quant: | |
585 w->quant_dc_chroma; | |
586 | |
587 //original intent dc_level+=predicted_dc/quant; but it got lost somewhere in the rounding | |
588 dc_level+= (w->predicted_dc*divide_quant + (1<<12) )>>13; | |
589 | |
590 dsp_x8_put_solidcolor( av_clip_uint8((dc_level*dc_quant+4)>>3), | |
591 s->dest[chroma], s->current_picture.linesize[!!chroma]); | |
592 | |
593 goto block_placed; | |
594 } | |
595 zeros_only = (dc_level == 0); | |
596 } | |
597 if(!chroma){ | |
598 s->block[0][0] = dc_level*w->quant; | |
599 }else{ | |
600 s->block[0][0] = dc_level*w->quant_dc_chroma; | |
601 } | |
602 | |
603 //there is !zero_only check in the original, but dc_level check is enough | |
604 if( (unsigned int)(dc_level+1) >= 3 && (w->edges&3) != 3 ){ | |
605 int direction; | |
606 /*ac_comp_direction[orient] = { 0, 3, 3, 1, 1, 0, 0, 0, 2, 2, 2, 1 };<- | |
607 -> 01'10' 10'10' 00'00' 00'01' 01'11' 11'00 =>0x6A017C */ | |
608 direction= (0x6A017C>>(w->orient*2))&3; | |
609 if (direction != 3){ | |
610 x8_ac_compensation(w, direction, s->block[0][0]);//modify block_last[] | |
611 } | |
612 } | |
613 | |
614 if(w->flat_dc){ | |
615 dsp_x8_put_solidcolor(w->predicted_dc, s->dest[chroma], s->current_picture.linesize[!!chroma]); | |
616 }else{ | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
617 s->dsp.x8_spatial_compensation[w->orient]( s->edge_emu_buffer, |
5887 | 618 s->dest[chroma], |
619 s->current_picture.linesize[!!chroma] ); | |
620 } | |
621 if(!zeros_only) | |
622 s->dsp.idct_add ( s->dest[chroma], | |
623 s->current_picture.linesize[!!chroma], | |
624 s->block[0] ); | |
625 | |
626 block_placed: | |
627 | |
628 if(!chroma){ | |
629 x8_update_predictions(w,w->orient,n); | |
630 } | |
631 | |
632 if(s->loop_filter){ | |
633 uint8_t* ptr = s->dest[chroma]; | |
634 int linesize = s->current_picture.linesize[!!chroma]; | |
635 | |
636 if(!( (w->edges&2) || ( zeros_only && (w->orient|4)==4 ) )){ | |
637 s->dsp.x8_h_loop_filter(ptr, linesize, w->quant); | |
638 } | |
639 if(!( (w->edges&1) || ( zeros_only && (w->orient|8)==8 ) )){ | |
640 s->dsp.x8_v_loop_filter(ptr, linesize, w->quant); | |
641 } | |
642 } | |
643 return 0; | |
644 } | |
645 | |
5898 | 646 static void x8_init_block_index(MpegEncContext *s){ //FIXME maybe merge with ff_* |
5887 | 647 //not s->linesize as this would be wrong for field pics |
5906 | 648 //not that IntraX8 has interlacing support ;) |
5887 | 649 const int linesize = s->current_picture.linesize[0]; |
650 const int uvlinesize= s->current_picture.linesize[1]; | |
651 | |
652 s->dest[0] = s->current_picture.data[0]; | |
653 s->dest[1] = s->current_picture.data[1]; | |
654 s->dest[2] = s->current_picture.data[2]; | |
655 | |
5897 | 656 s->dest[0] += s->mb_y * linesize << 3; |
5896 | 657 s->dest[1] += ( s->mb_y&(~1) ) * uvlinesize << 2;//chroma blocks are on add rows |
658 s->dest[2] += ( s->mb_y&(~1) ) * uvlinesize << 2; | |
5887 | 659 } |
660 | |
661 /** | |
662 * Initialize IntraX8 frame decoder. | |
663 * Requires valid MpegEncContext with valid s->mb_width before calling. | |
664 * @param w pointer to IntraX8Context | |
665 * @param s pointer to MpegEncContext of the parent codec | |
666 */ | |
8737
eeca2fc122f8
Add av_cold attributes to *_init and *_end functions.
alexc
parents:
8718
diff
changeset
|
667 av_cold void ff_intrax8_common_init(IntraX8Context * w, MpegEncContext * const s){ |
5887 | 668 |
669 w->s=s; | |
670 x8_vlc_init(); | |
671 assert(s->mb_width>0); | |
672 w->prediction_table=av_mallocz(s->mb_width*2*2);//two rows, 2 blocks per cannon mb | |
673 | |
674 ff_init_scantable(s->dsp.idct_permutation, &w->scantable[0], wmv1_scantable[0]); | |
675 ff_init_scantable(s->dsp.idct_permutation, &w->scantable[1], wmv1_scantable[2]); | |
676 ff_init_scantable(s->dsp.idct_permutation, &w->scantable[2], wmv1_scantable[3]); | |
677 } | |
678 | |
679 /** | |
6176
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
5907
diff
changeset
|
680 * Destroy IntraX8 frame structure. |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
5907
diff
changeset
|
681 * @param w pointer to IntraX8Context |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
5907
diff
changeset
|
682 */ |
8737
eeca2fc122f8
Add av_cold attributes to *_init and *_end functions.
alexc
parents:
8718
diff
changeset
|
683 av_cold void ff_intrax8_common_end(IntraX8Context * w) |
6176
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
5907
diff
changeset
|
684 { |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
5907
diff
changeset
|
685 av_freep(&w->prediction_table); |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
5907
diff
changeset
|
686 } |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
5907
diff
changeset
|
687 |
1d735690e172
Correctly clean up IntraX8Context upon codec close.
andoma
parents:
5907
diff
changeset
|
688 /** |
5887 | 689 * Decode single IntraX8 frame. |
690 * The parent codec must fill s->loopfilter and s->gb (bitstream). | |
5906 | 691 * The parent codec must call MPV_frame_start(), ff_er_frame_start() before calling this function. |
5887 | 692 * The parent codec must call ff_er_frame_end(), MPV_frame_end() after calling this function. |
693 * This function does not use MPV_decode_mb(). | |
694 * lowres decoding is theoretically impossible. | |
695 * @param w pointer to IntraX8Context | |
5906 | 696 * @param dquant doubled quantizer, it would be odd in case of VC-1 halfpq==1. |
697 * @param quant_offset offset away from zero | |
5887 | 698 */ |
699 //FIXME extern uint8_t wmv3_dc_scale_table[32]; | |
700 int ff_intrax8_decode_picture(IntraX8Context * const w, int dquant, int quant_offset){ | |
701 MpegEncContext * const s= w->s; | |
702 int mb_xy; | |
703 assert(s); | |
704 w->use_quant_matrix = get_bits1(&s->gb); | |
705 | |
706 w->dquant = dquant; | |
707 w->quant = dquant >> 1; | |
708 w->qsum = quant_offset; | |
709 | |
710 w->divide_quant_dc_luma = ((1<<16) + (w->quant>>1)) / w->quant; | |
711 if(w->quant < 5){ | |
712 w->quant_dc_chroma = w->quant; | |
713 w->divide_quant_dc_chroma = w->divide_quant_dc_luma; | |
714 }else{ | |
715 w->quant_dc_chroma = w->quant+((w->quant+3)>>3); | |
716 w->divide_quant_dc_chroma = ((1<<16) + (w->quant_dc_chroma>>1)) / w->quant_dc_chroma; | |
717 } | |
718 x8_reset_vlc_tables(w); | |
719 | |
720 s->resync_mb_x=0; | |
721 s->resync_mb_y=0; | |
722 | |
723 for(s->mb_y=0; s->mb_y < s->mb_height*2; s->mb_y++){ | |
724 x8_init_block_index(s); | |
725 mb_xy=(s->mb_y>>1)*s->mb_stride; | |
726 | |
727 for(s->mb_x=0; s->mb_x < s->mb_width*2; s->mb_x++){ | |
728 x8_get_prediction(w); | |
729 if(x8_setup_spatial_predictor(w,0)) goto error; | |
730 if(x8_decode_intra_mb(w,0)) goto error; | |
731 | |
732 if( s->mb_x & s->mb_y & 1 ){ | |
733 x8_get_prediction_chroma(w); | |
734 | |
735 /*when setting up chroma, no vlc is read, | |
5906 | 736 so no error condition can be reached*/ |
5887 | 737 x8_setup_spatial_predictor(w,1); |
738 if(x8_decode_intra_mb(w,1)) goto error; | |
739 | |
740 x8_setup_spatial_predictor(w,2); | |
741 if(x8_decode_intra_mb(w,2)) goto error; | |
742 | |
743 s->dest[1]+= 8; | |
744 s->dest[2]+= 8; | |
745 | |
746 /*emulate MB info in the relevant tables*/ | |
747 s->mbskip_table [mb_xy]=0; | |
748 s->mbintra_table[mb_xy]=1; | |
749 s->current_picture.qscale_table[mb_xy]=w->quant; | |
750 mb_xy++; | |
751 } | |
752 s->dest[0]+= 8; | |
753 } | |
754 if(s->mb_y&1){ | |
755 ff_draw_horiz_band(s, (s->mb_y-1)*8, 16); | |
756 } | |
757 } | |
758 | |
759 error: | |
760 ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, | |
761 (s->mb_x>>1)-1, (s->mb_y>>1)-1, | |
762 (AC_END|DC_END|MV_END) ); | |
763 return 0; | |
764 } |