ac3enc: select bandwidth based on bit rate, sample rate, and number of
[ffmpeg.git] / libavcodec / intrax8dsp.c
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 }