2 * This file is part of FFmpeg.
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.
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.
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
21 *@brief IntraX8 frame subdecoder image manipulation routines
27 area positions, #3 is 1 pixel only, other are 8 pixels
30 - -+--------+--------+
46 #define area5 (8+8+1+8)
47 #define area6 (8+8+1+16)
50 Collect statistics and prepare the edge pixels required by the other spatial compensation functions.
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 (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:
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;
62 4 - mb_x>= (mb_width-1) last block in the row, interpolate area #5;
64 static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize,
65 int * range, int * psum, int edges){
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.
86 if(!(edges&1)){//(mb_x!=0)//there is previous block on this row
87 ptr=src-1;//left column, area 2
89 c=*(ptr-1);//area1, same mb as area2, no need to check
94 min_pix=FFMIN(min_pix,c);
95 max_pix=FFMAX(max_pix,c);
102 if(!(edges&2)){ //(mb_y!=0)//there is row above
103 ptr=src-linesize;//top line
107 min_pix=FFMIN(min_pix, c);
108 max_pix=FFMAX(max_pix, c);
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);
114 memcpy(dst+area4, ptr, 16);//both area4 and 5
116 memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block
118 //now calculate the stuff we need
119 if(edges&3){//mb_x==0 || mb_y==0){
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
128 uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column
131 //edge pixel is not part of min/max
133 (*range) = max_pix - min_pix;
134 sum += *(dst+area5) + *(dst+area5+1);
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
150 static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
153 unsigned int p;//power divided by 2
155 uint16_t left_sum[2][8] = { { 0 } };
156 uint16_t top_sum[2][8] = { { 0 } };
162 left_sum[p&1][j]+= a>>(p>>1);
170 top_sum[p&1][j]+= a>>(p>>1);
177 top_sum[p&1][j]+= a>>(p>>1);
184 top_sum[p&1][j]+= a>>(p>>1);
189 top_sum [0][i]+=(top_sum [1][i]*181 + 128 )>>8;//181 is sqrt(2)/2
190 left_sum[0][i]+=(left_sum[1][i]*181 + 128 )>>8;
195 (uint32_t)top_sum [0][x]*zero_prediction_weights[y*16+x*2+0] +
196 (uint32_t)left_sum[0][y]*zero_prediction_weights[y*16+x*2+1] +
203 static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
208 dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
213 static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
218 dst[x]=src[area4 +1+y+x];
223 static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
228 dst[x]=src[area4 +((y+1)>>1)+x];
233 static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
238 dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
243 static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
249 dst[x]=src[area2+9+2*x-y];
251 dst[x]=src[area4 +x-((y+1)>>1)];
257 static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
262 dst[x]=src[area3+x-y];
267 static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
273 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
275 dst[x]=src[area2+8-y +(x>>1)];
281 static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
286 dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
291 static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
296 dst[x]=src[area2+6-FFMIN(x+y,6)];
301 static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
306 dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
311 static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
316 dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
322 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
324 int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
325 int ql=(quant+10)>>3;
327 for(i=0; i<8; i++,ptr+=b_stride){
340 (FFABS(p1-p2) <= ql) +
341 (FFABS(p2-p3) <= ql) +
342 (FFABS(p3-p4) <= ql) +
343 (FFABS(p4-p5) <= ql);
344 if(t>0){//You need at least 1 to be able to reach a total score of 6.
346 (FFABS(p5-p6) <= ql) +
347 (FFABS(p6-p7) <= ql) +
348 (FFABS(p7-p8) <= ql) +
349 (FFABS(p8-p9) <= ql) +
350 (FFABS(p0-p1) <= ql);
355 min=FFMIN(min,p3); max=FFMAX(max,p3);
356 min=FFMIN(min,p5); max=FFMAX(max,p5);
357 min=FFMIN(min,p8); max=FFMAX(max,p8);
358 if(max-min<2*quant){//early stop
359 min=FFMIN(min,p2); max=FFMAX(max,p2);
360 min=FFMIN(min,p4); max=FFMAX(max,p4);
361 min=FFMIN(min,p6); max=FFMAX(max,p6);
362 min=FFMIN(min,p7); max=FFMAX(max,p7);
364 ptr[-2*a_stride]=(4*p2 + 3*p3 + 1*p7 + 4)>>3;
365 ptr[-1*a_stride]=(3*p2 + 3*p4 + 2*p7 + 4)>>3;
366 ptr[ 0 ]=(2*p2 + 3*p5 + 3*p7 + 4)>>3;
367 ptr[ 1*a_stride]=(1*p2 + 3*p6 + 4*p7 + 4)>>3;
377 x0 = (2*p3 - 5*p4 + 5*p5 - 2*p6 + 4)>>3;
378 if(FFABS(x0) < quant){
379 x1=(2*p1 - 5*p2 + 5*p3 - 2*p4 + 4)>>3;
380 x2=(2*p5 - 5*p6 + 5*p7 - 2*p8 + 4)>>3;
382 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
385 if( x > 0 && (m^x0) <0){
389 m=(m^sign)-sign;//abs(m)
398 ptr[-1*a_stride] -= x;
406 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
407 x8_loop_filter(src, stride, 1, qscale);
410 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
411 x8_loop_filter(src, 1, stride, qscale);
414 av_cold void ff_intrax8dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
415 dsp->x8_h_loop_filter=x8_h_loop_filter;
416 dsp->x8_v_loop_filter=x8_v_loop_filter;
417 dsp->x8_setup_spatial_compensation=x8_setup_spatial_compensation;
418 dsp->x8_spatial_compensation[0]=spatial_compensation_0;
419 dsp->x8_spatial_compensation[1]=spatial_compensation_1;
420 dsp->x8_spatial_compensation[2]=spatial_compensation_2;
421 dsp->x8_spatial_compensation[3]=spatial_compensation_3;
422 dsp->x8_spatial_compensation[4]=spatial_compensation_4;
423 dsp->x8_spatial_compensation[5]=spatial_compensation_5;
424 dsp->x8_spatial_compensation[6]=spatial_compensation_6;
425 dsp->x8_spatial_compensation[7]=spatial_compensation_7;
426 dsp->x8_spatial_compensation[8]=spatial_compensation_8;
427 dsp->x8_spatial_compensation[9]=spatial_compensation_9;
428 dsp->x8_spatial_compensation[10]=spatial_compensation_10;
429 dsp->x8_spatial_compensation[11]=spatial_compensation_11;