Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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