ffmpeg / libavcodec / intrax8dsp.c @ 2912e87a
History  View  Annotate  Download (13 KB)
1 
/*


2 
* This file is part of Libav.

3 
*

4 
* Libav 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 
* Libav 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 Libav; if not, write to the Free Software

16 
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 021101301 USA

17 
*/

18  
19 
/**

20 
* @file

21 
*@brief IntraX8 frame subdecoder image manipulation routines

22 
*/

23  
24 
#include "dsputil.h" 
25  
26 
/*

27 
area positions, #3 is 1 pixel only, other are 8 pixels

28 
66666666

29 
34444444455555555

30 
 +++

31 
1 2XXXXXXXX

32 
1 2XXXXXXXX

33 
1 2XXXXXXXX

34 
1 2XXXXXXXX

35 
1 2XXXXXXXX

36 
1 2XXXXXXXX

37 
1 2XXXXXXXX

38 
1 2XXXXXXXX

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 
/**

50 
Collect statistics and prepare the edge pixels required by the other spatial compensation functions.

51 

52 
* @param src pointer to the beginning of the processed block

53 
* @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do.

54 
* @param linesize byte offset between 2 vertical pixels in the source image

55 
* @param range pointer to the variable where the edge pixel range is to be stored (maxmin 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:

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: 12  mb_x==mb_y==0  first block, use 0x80 value for all areas;

62 
4  mb_x>= (mb_width1) last block in the row, interpolate area #5;

63 
*/

64 
static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize, 
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=src1;//left column, area 2 
88 
for(i=7;i>=0;i){ 
89 
c=*(ptr1);//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=srclinesize;//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, ptrlinesize, 8);//area6 always present in the above block 
117 
} 
118 
//now calculate the stuff we need

119 
if(edges&3){//mb_x==0  mb_y==0){ 
120 
int avg=(sum+4)>>3; 
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 
} 
126 
sum+=avg*9;

127 
}else{

128 
uint8_t c=*(src1linesize);//the edge pixel, in the top line and left column 
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  
150 
static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){ 
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+7i]<<4; 
162 
for(j=0;j<8;j++){ 
163 
p=abs(ij); 
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(ij); 
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(ij); 
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(ij); 
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 
} 
205 
static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){ 
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 
} 
215 
static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){ 
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 
} 
225 
static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){ 
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 
} 
235 
static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){ 
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 
} 
245 
static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){ 
246 
int x,y;

247  
248 
for(y=0;y<8;y++){ 
249 
for(x=0;x<8;x++){ 
250 
if(2*xy<0){ 
251 
dst[x]=src[area2+9+2*xy]; 
252 
}else{

253 
dst[x]=src[area4 +x((y+1)>>1)]; 
254 
} 
255 
} 
256 
dst+=linesize; 
257 
} 
258 
} 
259 
static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){ 
260 
int x,y;

261  
262 
for(y=0;y<8;y++){ 
263 
for(x=0;x<8;x++){ 
264 
dst[x]=src[area3+xy]; 
265 
} 
266 
dst+=linesize; 
267 
} 
268 
} 
269 
static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){ 
270 
int x,y;

271  
272 
for(y=0;y<8;y++){ 
273 
for(x=0;x<8;x++){ 
274 
if(x2*y>0){ 
275 
dst[x]=( src[area31+x2*y] + src[area3+x2*y] + 1)>>1; 
276 
}else{

277 
dst[x]=src[area2+8y +(x>>1)]; 
278 
} 
279 
} 
280 
dst+=linesize; 
281 
} 
282 
} 
283 
static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){ 
284 
int x,y;

285  
286 
for(y=0;y<8;y++){ 
287 
for(x=0;x<8;x++){ 
288 
dst[x]=( src[area1+7y] + src[area2+7y] + 1 )>>1; 
289 
} 
290 
dst+=linesize; 
291 
} 
292 
} 
293 
static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){ 
294 
int x,y;

295  
296 
for(y=0;y<8;y++){ 
297 
for(x=0;x<8;x++){ 
298 
dst[x]=src[area2+6FFMIN(x+y,6)]; 
299 
} 
300 
dst+=linesize; 
301 
} 
302 
} 
303 
static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){ 
304 
int x,y;

305  
306 
for(y=0;y<8;y++){ 
307 
for(x=0;x<8;x++){ 
308 
dst[x]=(src[area2+7y]*(8x)+src[area4+x]*x+4)>>3; 
309 
} 
310 
dst+=linesize; 
311 
} 
312 
} 
313 
static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){ 
314 
int x,y;

315  
316 
for(y=0;y<8;y++){ 
317 
for(x=0;x<8;x++){ 
318 
dst[x]=(src[area2+7y]*y+src[area4+x]*(8y)+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(p1p2) <= ql) + 
343 
(FFABS(p2p3) <= ql) + 
344 
(FFABS(p3p4) <= ql) + 
345 
(FFABS(p4p5) <= ql); 
346 
if(t>0){//You need at least 1 to be able to reach a total score of 6. 
347 
t+= 
348 
(FFABS(p5p6) <= ql) + 
349 
(FFABS(p6p7) <= ql) + 
350 
(FFABS(p7p8) <= ql) + 
351 
(FFABS(p8p9) <= ql) + 
352 
(FFABS(p0p1) <= 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(maxmin<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(maxmin<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=p4p5; 
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  
416 
av_cold void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) {

417 
dsp>x8_h_loop_filter=x8_h_loop_filter; 
418 
dsp>x8_v_loop_filter=x8_v_loop_filter; 
419 
dsp>x8_setup_spatial_compensation=x8_setup_spatial_compensation; 
420 
dsp>x8_spatial_compensation[0]=spatial_compensation_0;

421 
dsp>x8_spatial_compensation[1]=spatial_compensation_1;

422 
dsp>x8_spatial_compensation[2]=spatial_compensation_2;

423 
dsp>x8_spatial_compensation[3]=spatial_compensation_3;

424 
dsp>x8_spatial_compensation[4]=spatial_compensation_4;

425 
dsp>x8_spatial_compensation[5]=spatial_compensation_5;

426 
dsp>x8_spatial_compensation[6]=spatial_compensation_6;

427 
dsp>x8_spatial_compensation[7]=spatial_compensation_7;

428 
dsp>x8_spatial_compensation[8]=spatial_compensation_8;

429 
dsp>x8_spatial_compensation[9]=spatial_compensation_9;

430 
dsp>x8_spatial_compensation[10]=spatial_compensation_10;

431 
dsp>x8_spatial_compensation[11]=spatial_compensation_11;

432 
} 