annotate ffmpeg/libavcodec/intrax8dsp.c @ 13:844d341cf643 tip

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