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