Statistics
| Branch: | Revision:

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 02110-1301 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
  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
/**
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 (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;
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=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
    }
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=*(src-1-linesize);//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+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
}
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*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
}
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+x-y];
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(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
}
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+7-y] + src[area2+7-y] + 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+6-FFMIN(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+7-y]*(8-x)+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+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);
346
        if(t>0){//You need at least 1 to be able to reach a total score of 6.
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

    
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
}