2 * This file is part of Libav.
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.
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.
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 02110-1301 USA
21 *@brief IntraX8 frame subdecoder image manipulation routines
25 #include "intrax8dsp.h"
26 #include "libavutil/common.h"
29 area positions, #3 is 1 pixel only, other are 8 pixels
32 - -+--------+--------+
48 #define area5 (8+8+1+8)
49 #define area6 (8+8+1+16)
52 Collect statistics and prepare the edge pixels required by the other spatial compensation functions.
54 * @param src pointer to the beginning of the processed block
55 * @param dst pointer to emu_edge, edge pixels are stored the way other compensation routines do.
56 * @param linesize byte offset between 2 vertical pixels in the source image
57 * @param range pointer to the variable where the edge pixel range is to be stored (max-min values)
58 * @param psum pointer to the variable where the edge pixel sum is to be stored
59 * @param edges Informs this routine that the block is on an image border, so it has to interpolate the missing edge pixels.
60 and some of the edge pixels should be interpolated, the flag has the following meaning:
61 1 - mb_x==0 - first block in the row, interpolate area #1,#2,#3;
62 2 - mb_y==0 - first row, interpolate area #3,#4,#5,#6;
63 note: 1|2 - mb_x==mb_y==0 - first block, use 0x80 value for all areas;
64 4 - mb_x>= (mb_width-1) last block in the row, interpolate area #5;
66 static void x8_setup_spatial_compensation(uint8_t *src, uint8_t *dst, int linesize,
67 int * range, int * psum, int edges){
77 memset(dst,0x80,16+1+16+8);
78 //this triggers flat_dc for sure.
79 //flat_dc avoids all (other) prediction modes, but requires dc_level decoding.
88 if(!(edges&1)){//(mb_x!=0)//there is previous block on this row
89 ptr=src-1;//left column, area 2
91 c=*(ptr-1);//area1, same mb as area2, no need to check
96 min_pix=FFMIN(min_pix,c);
97 max_pix=FFMAX(max_pix,c);
104 if(!(edges&2)){ //(mb_y!=0)//there is row above
105 ptr=src-linesize;//top line
109 min_pix=FFMIN(min_pix, c);
110 max_pix=FFMAX(max_pix, c);
112 if(edges&4){//last block on the row?
113 memset(dst+area5,c,8);//set with last pixel fr
114 memcpy(dst+area4, ptr, 8);
116 memcpy(dst+area4, ptr, 16);//both area4 and 5
118 memcpy(dst+area6, ptr-linesize, 8);//area6 always present in the above block
120 //now calculate the stuff we need
121 if(edges&3){//mb_x==0 || mb_y==0){
123 if(edges&1){ //(mb_x==0) {//implies mb_y!=0
124 memset(dst+area1,avg,8+8+1);//areas 1,2 and 3 are averaged
125 }else{//implies y==0 x!=0
126 memset(dst+area3,avg, 1+16+8);//areas 3, 4,5,6
130 uint8_t c=*(src-1-linesize);//the edge pixel, in the top line and left column
133 //edge pixel is not part of min/max
135 (*range) = max_pix - min_pix;
136 sum += *(dst+area5) + *(dst+area5+1);
141 static const uint16_t zero_prediction_weights[64*2] = {
142 640, 640, 669, 480, 708, 354, 748, 257, 792, 198, 760, 143, 808, 101, 772, 72,
143 480, 669, 537, 537, 598, 416, 661, 316, 719, 250, 707, 185, 768, 134, 745, 97,
144 354, 708, 416, 598, 488, 488, 564, 388, 634, 317, 642, 241, 716, 179, 706, 132,
145 257, 748, 316, 661, 388, 564, 469, 469, 543, 395, 571, 311, 655, 238, 660, 180,
146 198, 792, 250, 719, 317, 634, 395, 543, 469, 469, 507, 380, 597, 299, 616, 231,
147 161, 855, 206, 788, 266, 710, 340, 623, 411, 548, 455, 455, 548, 366, 576, 288,
148 122, 972, 159, 914, 211, 842, 276, 758, 341, 682, 389, 584, 483, 483, 520, 390,
149 110, 1172, 144, 1107, 193, 1028, 254, 932, 317, 846, 366, 731, 458, 611, 499, 499
152 static void spatial_compensation_0(uint8_t *src , uint8_t *dst, int linesize){
155 unsigned int p;//power divided by 2
157 uint16_t left_sum[2][8] = { { 0 } };
158 uint16_t top_sum[2][8] = { { 0 } };
164 left_sum[p&1][j]+= a>>(p>>1);
172 top_sum[p&1][j]+= a>>(p>>1);
179 top_sum[p&1][j]+= a>>(p>>1);
186 top_sum[p&1][j]+= a>>(p>>1);
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;
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] +
205 static void spatial_compensation_1(uint8_t *src , uint8_t *dst, int linesize){
210 dst[x]=src[area4 + FFMIN(2*y+x+2, 15) ];
215 static void spatial_compensation_2(uint8_t *src , uint8_t *dst, int linesize){
220 dst[x]=src[area4 +1+y+x];
225 static void spatial_compensation_3(uint8_t *src , uint8_t *dst, int linesize){
230 dst[x]=src[area4 +((y+1)>>1)+x];
235 static void spatial_compensation_4(uint8_t *src , uint8_t *dst, int linesize){
240 dst[x]=( src[area4+x] + src[area6+x] + 1 )>>1;
245 static void spatial_compensation_5(uint8_t *src , uint8_t *dst, int linesize){
251 dst[x]=src[area2+9+2*x-y];
253 dst[x]=src[area4 +x-((y+1)>>1)];
259 static void spatial_compensation_6(uint8_t *src , uint8_t *dst, int linesize){
264 dst[x]=src[area3+x-y];
269 static void spatial_compensation_7(uint8_t *src , uint8_t *dst, int linesize){
275 dst[x]=( src[area3-1+x-2*y] + src[area3+x-2*y] + 1)>>1;
277 dst[x]=src[area2+8-y +(x>>1)];
283 static void spatial_compensation_8(uint8_t *src , uint8_t *dst, int linesize){
288 dst[x]=( src[area1+7-y] + src[area2+7-y] + 1 )>>1;
293 static void spatial_compensation_9(uint8_t *src , uint8_t *dst, int linesize){
298 dst[x]=src[area2+6-FFMIN(x+y,6)];
303 static void spatial_compensation_10(uint8_t *src , uint8_t *dst, int linesize){
308 dst[x]=(src[area2+7-y]*(8-x)+src[area4+x]*x+4)>>3;
313 static void spatial_compensation_11(uint8_t *src , uint8_t *dst, int linesize){
318 dst[x]=(src[area2+7-y]*y+src[area4+x]*(8-y)+4)>>3;
324 static void x8_loop_filter(uint8_t * ptr, const int a_stride, const int b_stride, int quant){
326 int p0,p1,p2,p3,p4,p5,p6,p7,p8,p9;
327 int ql=(quant+10)>>3;
329 for(i=0; i<8; i++,ptr+=b_stride){
342 (FFABS(p1-p2) <= ql) +
343 (FFABS(p2-p3) <= ql) +
344 (FFABS(p3-p4) <= ql) +
345 (FFABS(p4-p5) <= ql);
346 if(t>0){//You need at least 1 to be able to reach a total score of 6.
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);
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);
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;
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;
384 x=FFABS(x0) - FFMIN( FFABS(x1), FFABS(x2) );
387 if( x > 0 && (m^x0) <0){
391 m=(m^sign)-sign;//abs(m)
400 ptr[-1*a_stride] -= x;
408 static void x8_h_loop_filter(uint8_t *src, int stride, int qscale){
409 x8_loop_filter(src, stride, 1, qscale);
412 static void x8_v_loop_filter(uint8_t *src, int stride, int qscale){
413 x8_loop_filter(src, 1, stride, qscale);
416 av_cold void ff_intrax8dsp_init(IntraX8DSPContext *dsp)
418 dsp->h_loop_filter=x8_h_loop_filter;
419 dsp->v_loop_filter=x8_v_loop_filter;
420 dsp->setup_spatial_compensation=x8_setup_spatial_compensation;
421 dsp->spatial_compensation[0]=spatial_compensation_0;
422 dsp->spatial_compensation[1]=spatial_compensation_1;
423 dsp->spatial_compensation[2]=spatial_compensation_2;
424 dsp->spatial_compensation[3]=spatial_compensation_3;
425 dsp->spatial_compensation[4]=spatial_compensation_4;
426 dsp->spatial_compensation[5]=spatial_compensation_5;
427 dsp->spatial_compensation[6]=spatial_compensation_6;
428 dsp->spatial_compensation[7]=spatial_compensation_7;
429 dsp->spatial_compensation[8]=spatial_compensation_8;
430 dsp->spatial_compensation[9]=spatial_compensation_9;
431 dsp->spatial_compensation[10]=spatial_compensation_10;
432 dsp->spatial_compensation[11]=spatial_compensation_11;