Mercurial > libavcodec.hg
annotate intrax8dsp.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 | bf309c7ce615 |
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:
5907
diff
changeset
|
20 * @file libavcodec/intrax8dsp.c |
5906 | 21 *@brief IntraX8 frame subdecoder image manipulation routines |
5887 | 22 */ |
23 | |
24 #include "dsputil.h" | |
25 | |
26 /* | |
27 area positions, #3 is 1 pixel only, other are 8 pixels | |
28 |66666666| | |
29 3|44444444|55555555| | |
30 - -+--------+--------+ | |
31 1 2|XXXXXXXX| | |
32 1 2|XXXXXXXX| | |
33 1 2|XXXXXXXX| | |
34 1 2|XXXXXXXX| | |
35 1 2|XXXXXXXX| | |
36 1 2|XXXXXXXX| | |
37 1 2|XXXXXXXX| | |
38 1 2|XXXXXXXX| | |
39 ^-start | |
40 */ | |
41 | |
42 #define area1 (0) | |
43 #define area2 (8) | |
44 #define area3 (8+8) | |
45 #define area4 (8+8+1) | |
46 #define area5 (8+8+1+8) | |
47 #define area6 (8+8+1+16) | |
48 | |
49 /** | |
5906 | 50 Collect statistics and prepare the edge pixels required by the other spatial compensation functions. |
5887 | 51 |
52 * @param src pointer to the beginning of the processed block | |
5906 | 53 * @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do. |
5887 | 54 * @param linesize byte offset between 2 vertical pixels in the source image |
5906 | 55 * @param range pointer to the variable where the edge pixel range is to be stored (max-min values) |
56 * @param psum pointer to the variable where the edge pixel sum is to be stored | |
57 * @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge pixels. | |
58 and some of the edge pixels should be interpolated, the flag has the following meaning: | |
5887 | 59 1 - mb_x==0 - first block in the row, interpolate area #1,#2,#3; |
60 2 - mb_y==0 - first row, interpolate area #3,#4,#5,#6; | |
61 note: 1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas; | |
5906 | 62 4 - mb_x>= (mb_width-1) last block in the row, interpolate area #5; |
5887 | 63 */ |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
64 static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize, |
5887 | 65 int * range, int * psum, int edges){ |
66 uint8_t * ptr; | |
67 int sum; | |
68 int i; | |
69 int min_pix,max_pix; | |
70 uint8_t c; | |
71 | |
72 if((edges&3)==3){ | |
73 *psum=0x80*(8+1+8+2); | |
74 *range=0; | |
75 memset(dst,0x80,16+1+16+8); | |
76 //this triggers flat_dc for sure. | |
77 //flat_dc avoids all (other) prediction modes, but requires dc_level decoding. | |
78 return; | |
79 } | |
80 | |
81 min_pix=256; | |
82 max_pix=-1; | |
83 | |
84 sum=0; | |
85 | |
86 if(!(edges&1)){//(mb_x!=0)//there is previous block on this row | |
87 ptr=src-1;//left column, area 2 | |
88 for(i=7;i>=0;i--){ | |
89 c=*(ptr-1);//area1, same mb as area2, no need to check | |
90 dst[area1+i]=c; | |
91 c=*(ptr); | |
92 | |
93 sum+=c; | |
94 min_pix=FFMIN(min_pix,c); | |
95 max_pix=FFMAX(max_pix,c); | |
96 dst[area2+i]=c; | |
97 | |
98 ptr+=linesize; | |
99 } | |
100 } | |
101 | |
102 if(!(edges&2)){ //(mb_y!=0)//there is row above | |
103 ptr=src-linesize;//top line | |
104 for(i=0;i<8;i++){ | |
105 c=*(ptr+i); | |
106 sum+=c; | |
107 min_pix=FFMIN(min_pix, c); | |
108 max_pix=FFMAX(max_pix, c); | |
109 } | |
110 if(edges&4){//last block on the row? | |
111 memset(dst+area5,c,8);//set with last pixel fr | |
112 memcpy(dst+area4, ptr, 8); | |
113 }else{ | |
114 memcpy(dst+area4, ptr, 16);//both area4 and 5 | |
115 } | |
116 memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block | |
117 } | |
5906 | 118 //now calculate the stuff we need |
5887 | 119 if(edges&3){//mb_x==0 || mb_y==0){ |
5888 | 120 int avg=(sum+4)>>3; |
5887 | 121 if(edges&1){ //(mb_x==0) {//implies mb_y!=0 |
122 memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged | |
123 }else{//implies y==0 x!=0 | |
124 memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6 | |
125 } | |
5888 | 126 sum+=avg*9; |
5887 | 127 }else{ |
5906 | 128 uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column |
5887 | 129 dst[area3]=c; |
130 sum+=c; | |
131 //edge pixel is not part of min/max | |
132 } | |
133 (*range) = max_pix - min_pix; | |
134 sum += *(dst+area5) + *(dst+area5+1); | |
135 *psum = sum; | |
136 } | |
137 | |
138 | |
139 static const uint16_t zero_prediction_weights[64*2] = { | |
140 640, 640, 669, 480, 708, 354, 748, 257, 792, 198, 760, 143, 808, 101, 772, 72, | |
141 480, 669, 537, 537, 598, 416, 661, 316, 719, 250, 707, 185, 768, 134, 745, 97, | |
142 354, 708, 416, 598, 488, 488, 564, 388, 634, 317, 642, 241, 716, 179, 706, 132, | |
143 257, 748, 316, 661, 388, 564, 469, 469, 543, 395, 571, 311, 655, 238, 660, 180, | |
144 198, 792, 250, 719, 317, 634, 395, 543, 469, 469, 507, 380, 597, 299, 616, 231, | |
145 161, 855, 206, 788, 266, 710, 340, 623, 411, 548, 455, 455, 548, 366, 576, 288, | |
146 122, 972, 159, 914, 211, 842, 276, 758, 341, 682, 389, 584, 483, 483, 520, 390, | |
147 110, 1172, 144, 1107, 193, 1028, 254, 932, 317, 846, 366, 731, 458, 611, 499, 499 | |
148 }; | |
149 | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
150 static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 151 int i,j; |
152 int x,y; | |
153 unsigned int p;//power divided by 2 | |
154 int a; | |
155 uint16_t left_sum[2][8]; | |
156 uint16_t top_sum[2][8]; | |
157 memset(left_sum,0,2*8*sizeof(uint16_t)); | |
158 memset( top_sum,0,2*8*sizeof(uint16_t)); | |
159 | |
160 for(i=0;i<8;i++){ | |
161 a=src[area2+7-i]<<4; | |
162 for(j=0;j<8;j++){ | |
163 p=abs(i-j); | |
164 left_sum[p&1][j]+= a>>(p>>1); | |
165 } | |
166 } | |
167 | |
168 for(i=0;i<8;i++){ | |
169 a=src[area4+i]<<4; | |
170 for(j=0;j<8;j++){ | |
171 p=abs(i-j); | |
172 top_sum[p&1][j]+= a>>(p>>1); | |
173 } | |
174 } | |
175 for(;i<10;i++){ | |
176 a=src[area4+i]<<4; | |
177 for(j=5;j<8;j++){ | |
178 p=abs(i-j); | |
179 top_sum[p&1][j]+= a>>(p>>1); | |
180 } | |
181 } | |
182 for(;i<12;i++){ | |
183 a=src[area4+i]<<4; | |
184 for(j=7;j<8;j++){ | |
185 p=abs(i-j); | |
186 top_sum[p&1][j]+= a>>(p>>1); | |
187 } | |
188 } | |
189 | |
190 for(i=0;i<8;i++){ | |
191 top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2 | |
192 left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8; | |
193 } | |
194 for(y=0;y<8;y++){ | |
195 for(x=0;x<8;x++){ | |
196 dst[x] = ( | |
197 (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] + | |
198 (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] + | |
199 0x8000 | |
200 )>>16; | |
201 } | |
202 dst+=linesize; | |
203 } | |
204 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
205 static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 206 int x,y; |
207 | |
208 for(y=0;y<8;y++){ | |
209 for(x=0;x<8;x++){ | |
210 dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ]; | |
211 } | |
212 dst+=linesize; | |
213 } | |
214 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
215 static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 216 int x,y; |
217 | |
218 for(y=0;y<8;y++){ | |
219 for(x=0;x<8;x++){ | |
220 dst[x]=src[area4 +1+y+x]; | |
221 } | |
222 dst+=linesize; | |
223 } | |
224 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
225 static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 226 int x,y; |
227 | |
228 for(y=0;y<8;y++){ | |
229 for(x=0;x<8;x++){ | |
230 dst[x]=src[area4 +((y+1)>>1)+x]; | |
231 } | |
232 dst+=linesize; | |
233 } | |
234 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
235 static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 236 int x,y; |
237 | |
238 for(y=0;y<8;y++){ | |
239 for(x=0;x<8;x++){ | |
240 dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1; | |
241 } | |
242 dst+=linesize; | |
243 } | |
244 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
245 static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 246 int x,y; |
247 | |
248 for(y=0;y<8;y++){ | |
249 for(x=0;x<8;x++){ | |
250 if(2*x-y<0){ | |
251 dst[x]=src[area2+9+2*x-y]; | |
252 }else{ | |
253 dst[x]=src[area4 +x-((y+1)>>1)]; | |
254 } | |
255 } | |
256 dst+=linesize; | |
257 } | |
258 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
259 static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 260 int x,y; |
261 | |
262 for(y=0;y<8;y++){ | |
263 for(x=0;x<8;x++){ | |
264 dst[x]=src[area3+x-y]; | |
265 } | |
266 dst+=linesize; | |
267 } | |
268 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
269 static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 270 int x,y; |
271 | |
272 for(y=0;y<8;y++){ | |
273 for(x=0;x<8;x++){ | |
274 if(x-2*y>0){ | |
275 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1; | |
276 }else{ | |
277 dst[x]=src[area2+8-y +(x>>1)]; | |
278 } | |
279 } | |
280 dst+=linesize; | |
281 } | |
282 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
283 static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 284 int x,y; |
285 | |
286 for(y=0;y<8;y++){ | |
287 for(x=0;x<8;x++){ | |
288 dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1; | |
289 } | |
290 dst+=linesize; | |
291 } | |
292 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
293 static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 294 int x,y; |
295 | |
296 for(y=0;y<8;y++){ | |
297 for(x=0;x<8;x++){ | |
298 dst[x]=src[area2+6-FFMIN(x+y,6)]; | |
299 } | |
300 dst+=linesize; | |
301 } | |
302 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
303 static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 304 int x,y; |
305 | |
306 for(y=0;y<8;y++){ | |
307 for(x=0;x<8;x++){ | |
308 dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3; | |
309 } | |
310 dst+=linesize; | |
311 } | |
312 } | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
313 static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){ |
5887 | 314 int x,y; |
315 | |
316 for(y=0;y<8;y++){ | |
317 for(x=0;x<8;x++){ | |
318 dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3; | |
319 } | |
320 dst+=linesize; | |
321 } | |
322 } | |
323 | |
324 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){ | |
325 int i,t; | |
326 int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9; | |
327 int ql=(quant+10)>>3; | |
328 | |
329 for(i=0; i<8; i++,ptr+=b_stride){ | |
330 p0=ptr[-5*a_stride]; | |
331 p1=ptr[-4*a_stride]; | |
332 p2=ptr[-3*a_stride]; | |
333 p3=ptr[-2*a_stride]; | |
334 p4=ptr[-1*a_stride]; | |
335 p5=ptr[ 0 ]; | |
336 p6=ptr[ 1*a_stride]; | |
337 p7=ptr[ 2*a_stride]; | |
338 p8=ptr[ 3*a_stride]; | |
339 p9=ptr[ 4*a_stride]; | |
340 | |
341 t= | |
342 (FFABS(p1-p2) <= ql) + | |
343 (FFABS(p2-p3) <= ql) + | |
344 (FFABS(p3-p4) <= ql) + | |
345 (FFABS(p4-p5) <= ql); | |
5906 | 346 if(t>0){//You need at least 1 to be able to reach a total score of 6. |
5887 | 347 t+= |
348 (FFABS(p5-p6) <= ql) + | |
349 (FFABS(p6-p7) <= ql) + | |
350 (FFABS(p7-p8) <= ql) + | |
351 (FFABS(p8-p9) <= ql) + | |
352 (FFABS(p0-p1) <= ql); | |
353 if(t>=6){ | |
354 int min,max; | |
355 | |
356 min=max=p1; | |
357 min=FFMIN(min,p3); max=FFMAX(max,p3); | |
358 min=FFMIN(min,p5); max=FFMAX(max,p5); | |
359 min=FFMIN(min,p8); max=FFMAX(max,p8); | |
360 if(max-min<2*quant){//early stop | |
361 min=FFMIN(min,p2); max=FFMAX(max,p2); | |
362 min=FFMIN(min,p4); max=FFMAX(max,p4); | |
363 min=FFMIN(min,p6); max=FFMAX(max,p6); | |
364 min=FFMIN(min,p7); max=FFMAX(max,p7); | |
365 if(max-min<2*quant){ | |
366 ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3; | |
367 ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3; | |
368 ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3; | |
369 ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3; | |
370 continue; | |
371 }; | |
372 } | |
373 } | |
374 } | |
375 { | |
376 int x,x0,x1,x2; | |
377 int m; | |
378 | |
379 x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3; | |
380 if(FFABS(x0) < quant){ | |
381 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3; | |
382 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3; | |
383 | |
384 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) ); | |
385 m=p4-p5; | |
386 | |
387 if( x > 0 && (m^x0) <0){ | |
388 int32_t sign; | |
389 | |
390 sign=m>>31; | |
391 m=(m^sign)-sign;//abs(m) | |
392 m>>=1; | |
393 | |
394 x=(5*x)>>3; | |
395 | |
396 if(x>m) x=m; | |
397 | |
398 x=(x^sign)-sign; | |
399 | |
400 ptr[-1*a_stride] -= x; | |
401 ptr[ 0] += x; | |
402 } | |
403 } | |
404 } | |
405 } | |
406 } | |
407 | |
408 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){ | |
409 x8_loop_filter(src, stride, 1, qscale); | |
410 } | |
411 | |
412 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){ | |
413 x8_loop_filter(src, 1, stride, qscale); | |
414 } | |
415 | |
10867 | 416 av_cold void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) { |
5887 | 417 dsp->x8_h_loop_filter=x8_h_loop_filter; |
418 dsp->x8_v_loop_filter=x8_v_loop_filter; | |
5907
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
419 dsp->x8_setup_spatial_compensation=x8_setup_spatial_compensation; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
420 dsp->x8_spatial_compensation[0]=spatial_compensation_0; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
421 dsp->x8_spatial_compensation[1]=spatial_compensation_1; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
422 dsp->x8_spatial_compensation[2]=spatial_compensation_2; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
423 dsp->x8_spatial_compensation[3]=spatial_compensation_3; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
424 dsp->x8_spatial_compensation[4]=spatial_compensation_4; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
425 dsp->x8_spatial_compensation[5]=spatial_compensation_5; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
426 dsp->x8_spatial_compensation[6]=spatial_compensation_6; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
427 dsp->x8_spatial_compensation[7]=spatial_compensation_7; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
428 dsp->x8_spatial_compensation[8]=spatial_compensation_8; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
429 dsp->x8_spatial_compensation[9]=spatial_compensation_9; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
430 dsp->x8_spatial_compensation[10]=spatial_compensation_10; |
fbd10e6dfbe1
cosmetics: Fix spacial --> spatial typo in function names.
diego
parents:
5906
diff
changeset
|
431 dsp->x8_spatial_compensation[11]=spatial_compensation_11; |
5887 | 432 } |