dwt: check malloc calls
[ffmpeg.git] / libavcodec / dwt.c
1 /*
2  * Copyright (C) 2004-2010 Michael Niedermayer <michaelni@gmx.at>
3  *
4  * This file is part of Libav.
5  *
6  * Libav is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * Libav is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "libavutil/attributes.h"
22 #include "dsputil.h"
23 #include "dwt.h"
24
25 void ff_slice_buffer_init(slice_buffer *buf, int line_count,
26                           int max_allocated_lines, int line_width,
27                           IDWTELEM *base_buffer)
28 {
29     int i;
30
31     buf->base_buffer = base_buffer;
32     buf->line_count  = line_count;
33     buf->line_width  = line_width;
34     buf->data_count  = max_allocated_lines;
35     buf->line        = av_mallocz(sizeof(IDWTELEM *) * line_count);
36     if (!buf->line)
37         return AVERROR(ENOMEM);
38     buf->data_stack  = av_malloc(sizeof(IDWTELEM *) * max_allocated_lines);
39     if (!buf->data_stack) {
40         av_free(buf->line);
41         return AVERROR(ENOMEM);
42     }
43
44     for (i = 0; i < max_allocated_lines; i++) {
45         buf->data_stack[i] = av_malloc(sizeof(IDWTELEM) * line_width);
46         if (!buf->data_stack[i]) {
47             for (i--; i >=0; i--)
48                 av_free(buf->data_stack[i]);
49             av_free(buf->data_stack);
50             av_free(buf->line);
51             return AVERROR(ENOMEM);
52         }
53     }
54
55     buf->data_stack_top = max_allocated_lines - 1;
56 }
57
58 IDWTELEM *ff_slice_buffer_load_line(slice_buffer *buf, int line)
59 {
60     IDWTELEM *buffer;
61
62     assert(buf->data_stack_top >= 0);
63 //  assert(!buf->line[line]);
64     if (buf->line[line])
65         return buf->line[line];
66
67     buffer = buf->data_stack[buf->data_stack_top];
68     buf->data_stack_top--;
69     buf->line[line] = buffer;
70
71     return buffer;
72 }
73
74 void ff_slice_buffer_release(slice_buffer *buf, int line)
75 {
76     IDWTELEM *buffer;
77
78     assert(line >= 0 && line < buf->line_count);
79     assert(buf->line[line]);
80
81     buffer = buf->line[line];
82     buf->data_stack_top++;
83     buf->data_stack[buf->data_stack_top] = buffer;
84     buf->line[line]                      = NULL;
85 }
86
87 void ff_slice_buffer_flush(slice_buffer *buf)
88 {
89     int i;
90     for (i = 0; i < buf->line_count; i++)
91         if (buf->line[i])
92             ff_slice_buffer_release(buf, i);
93 }
94
95 void ff_slice_buffer_destroy(slice_buffer *buf)
96 {
97     int i;
98     ff_slice_buffer_flush(buf);
99
100     for (i = buf->data_count - 1; i >= 0; i--)
101         av_freep(&buf->data_stack[i]);
102     av_freep(&buf->data_stack);
103     av_freep(&buf->line);
104 }
105
106 static inline int mirror(int v, int m)
107 {
108     while ((unsigned)v > (unsigned)m) {
109         v = -v;
110         if (v < 0)
111             v += 2 * m;
112     }
113     return v;
114 }
115
116 static av_always_inline void lift(DWTELEM *dst, DWTELEM *src, DWTELEM *ref,
117                                   int dst_step, int src_step, int ref_step,
118                                   int width, int mul, int add, int shift,
119                                   int highpass, int inverse)
120 {
121     const int mirror_left  = !highpass;
122     const int mirror_right = (width & 1) ^ highpass;
123     const int w            = (width >> 1) - 1 + (highpass & width);
124     int i;
125
126 #define LIFT(src, ref, inv) ((src) + ((inv) ? -(ref) : +(ref)))
127     if (mirror_left) {
128         dst[0] = LIFT(src[0], ((mul * 2 * ref[0] + add) >> shift), inverse);
129         dst   += dst_step;
130         src   += src_step;
131     }
132
133     for (i = 0; i < w; i++)
134         dst[i * dst_step] = LIFT(src[i * src_step],
135                                  ((mul * (ref[i * ref_step] +
136                                           ref[(i + 1) * ref_step]) +
137                                    add) >> shift),
138                                  inverse);
139
140     if (mirror_right)
141         dst[w * dst_step] = LIFT(src[w * src_step],
142                                  ((mul * 2 * ref[w * ref_step] + add) >> shift),
143                                  inverse);
144 }
145
146 static av_always_inline void inv_lift(IDWTELEM *dst, IDWTELEM *src, IDWTELEM *ref,
147                                       int dst_step, int src_step, int ref_step,
148                                       int width, int mul, int add, int shift,
149                                       int highpass, int inverse)
150 {
151     const int mirror_left  = !highpass;
152     const int mirror_right = (width & 1) ^ highpass;
153     const int w            = (width >> 1) - 1 + (highpass & width);
154     int i;
155
156 #define LIFT(src, ref, inv) ((src) + ((inv) ? -(ref) : +(ref)))
157     if (mirror_left) {
158         dst[0] = LIFT(src[0], ((mul * 2 * ref[0] + add) >> shift), inverse);
159         dst   += dst_step;
160         src   += src_step;
161     }
162
163     for (i = 0; i < w; i++)
164         dst[i * dst_step] = LIFT(src[i * src_step],
165                                  ((mul * (ref[i * ref_step] +
166                                           ref[(i + 1) * ref_step]) +
167                                    add) >> shift),
168                                  inverse);
169
170     if (mirror_right) {
171         dst[w * dst_step] = LIFT(src[w * src_step],
172                                  ((mul * 2 * ref[w * ref_step] + add) >> shift),
173                                  inverse);
174     }
175 }
176
177 #ifndef liftS
178 static av_always_inline void liftS(DWTELEM *dst, DWTELEM *src, DWTELEM *ref,
179                                    int dst_step, int src_step, int ref_step,
180                                    int width, int mul, int add, int shift,
181                                    int highpass, int inverse)
182 {
183     const int mirror_left  = !highpass;
184     const int mirror_right = (width & 1) ^ highpass;
185     const int w            = (width >> 1) - 1 + (highpass & width);
186     int i;
187
188     assert(shift == 4);
189 #define LIFTS(src, ref, inv)                                            \
190     ((inv) ? (src) + (((ref) + 4 * (src)) >> shift)                     \
191            : -((-16 * (src) + (ref) + add /                             \
192                 4 + 1 + (5 << 25)) / (5 * 4) - (1 << 23)))
193     if (mirror_left) {
194         dst[0] = LIFTS(src[0], mul * 2 * ref[0] + add, inverse);
195         dst   += dst_step;
196         src   += src_step;
197     }
198
199     for (i = 0; i < w; i++)
200         dst[i * dst_step] = LIFTS(src[i * src_step],
201                                   mul * (ref[i * ref_step] +
202                                          ref[(i + 1) * ref_step]) + add,
203                                   inverse);
204
205     if (mirror_right)
206         dst[w * dst_step] = LIFTS(src[w * src_step],
207                                   mul * 2 * ref[w * ref_step] + add,
208                                   inverse);
209 }
210
211 static av_always_inline void inv_liftS(IDWTELEM *dst, IDWTELEM *src,
212                                        IDWTELEM *ref, int dst_step,
213                                        int src_step, int ref_step,
214                                        int width, int mul, int add, int shift,
215                                        int highpass, int inverse)
216 {
217     const int mirror_left  = !highpass;
218     const int mirror_right = (width & 1) ^ highpass;
219     const int w            = (width >> 1) - 1 + (highpass & width);
220     int i;
221
222     assert(shift == 4);
223 #define LIFTS(src, ref, inv)                                            \
224     ((inv) ? (src) + (((ref) + 4 * (src)) >> shift)                     \
225            : -((-16 * (src) + (ref) + add /                             \
226                 4 + 1 + (5 << 25)) / (5 * 4) - (1 << 23)))
227     if (mirror_left) {
228         dst[0] = LIFTS(src[0], mul * 2 * ref[0] + add, inverse);
229         dst   += dst_step;
230         src   += src_step;
231     }
232
233     for (i = 0; i < w; i++)
234         dst[i * dst_step] = LIFTS(src[i * src_step],
235                                   mul * (ref[i * ref_step] +
236                                          ref[(i + 1) * ref_step]) + add,
237                                   inverse);
238
239     if (mirror_right)
240         dst[w * dst_step] = LIFTS(src[w * src_step],
241                                   mul * 2 * ref[w * ref_step] + add, inverse);
242 }
243 #endif /* ! liftS */
244
245 static void horizontal_decompose53i(DWTELEM *b, int width)
246 {
247     DWTELEM temp[width];
248     const int width2 = width >> 1;
249     int x;
250     const int w2 = (width + 1) >> 1;
251
252     for (x = 0; x < width2; x++) {
253         temp[x]      = b[2 * x];
254         temp[x + w2] = b[2 * x + 1];
255     }
256     if (width & 1)
257         temp[x] = b[2 * x];
258 #if 0
259     {
260         int A1, A2, A3, A4;
261         A2             = temp[1];
262         A4             = temp[0];
263         A1             = temp[0 + width2];
264         A1            -= (A2 + A4) >> 1;
265         A4            += (A1 +  1) >> 1;
266         b[0 + width2]  = A1;
267         b[0]           = A4;
268         for (x = 1; x + 1 < width2; x += 2) {
269             A3                 = temp[x + width2];
270             A4                 = temp[x + 1];
271             A3                -= (A2 + A4)     >> 1;
272             A2                += (A1 + A3 + 2) >> 2;
273             b[x + width2]      = A3;
274             b[x]               = A2;
275
276             A1                 = temp[x + 1 + width2];
277             A2                 = temp[x + 2];
278             A1                -= (A2 + A4)     >> 1;
279             A4                += (A1 + A3 + 2) >> 2;
280             b[x + 1 + width2]  = A1;
281             b[x + 1]           = A4;
282         }
283         A3            = temp[width - 1];
284         A3           -= A2;
285         A2           += (A1 + A3 + 2) >> 2;
286         b[width  - 1] = A3;
287         b[width2 - 1] = A2;
288     }
289 #else
290     lift(b + w2, temp + w2, temp,   1, 1, 1, width, -1, 0, 1, 1, 0);
291     lift(b,      temp,      b + w2, 1, 1, 1, width,  1, 2, 2, 0, 0);
292 #endif /* 0 */
293 }
294
295 static void vertical_decompose53iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
296                                     int width)
297 {
298     int i;
299
300     for (i = 0; i < width; i++)
301         b1[i] -= (b0[i] + b2[i]) >> 1;
302 }
303
304 static void vertical_decompose53iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
305                                     int width)
306 {
307     int i;
308
309     for (i = 0; i < width; i++)
310         b1[i] += (b0[i] + b2[i] + 2) >> 2;
311 }
312
313 static void spatial_decompose53i(DWTELEM *buffer, int width, int height,
314                                  int stride)
315 {
316     int y;
317     DWTELEM *b0 = buffer + mirror(-2 - 1, height - 1) * stride;
318     DWTELEM *b1 = buffer + mirror(-2,     height - 1) * stride;
319
320     for (y = -2; y < height; y += 2) {
321         DWTELEM *b2 = buffer + mirror(y + 1, height - 1) * stride;
322         DWTELEM *b3 = buffer + mirror(y + 2, height - 1) * stride;
323
324         if (y + 1 < (unsigned)height)
325             horizontal_decompose53i(b2, width);
326         if (y + 2 < (unsigned)height)
327             horizontal_decompose53i(b3, width);
328
329         if (y + 1 < (unsigned)height)
330             vertical_decompose53iH0(b1, b2, b3, width);
331         if (y + 0 < (unsigned)height)
332             vertical_decompose53iL0(b0, b1, b2, width);
333
334         b0 = b2;
335         b1 = b3;
336     }
337 }
338
339 static void horizontal_decompose97i(DWTELEM *b, int width)
340 {
341     DWTELEM temp[width];
342     const int w2 = (width + 1) >> 1;
343
344     lift(temp + w2, b + 1, b,         1, 2, 2, width, W_AM, W_AO, W_AS, 1, 1);
345     liftS(temp,     b,     temp + w2, 1, 2, 1, width, W_BM, W_BO, W_BS, 0, 0);
346     lift(b + w2, temp + w2, temp,     1, 1, 1, width, W_CM, W_CO, W_CS, 1, 0);
347     lift(b,      temp,      b + w2,   1, 1, 1, width, W_DM, W_DO, W_DS, 0, 0);
348 }
349
350 static void vertical_decompose97iH0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
351                                     int width)
352 {
353     int i;
354
355     for (i = 0; i < width; i++)
356         b1[i] -= (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS;
357 }
358
359 static void vertical_decompose97iH1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
360                                     int width)
361 {
362     int i;
363
364     for (i = 0; i < width; i++)
365         b1[i] += (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS;
366 }
367
368 static void vertical_decompose97iL0(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
369                                     int width)
370 {
371     int i;
372
373     for (i = 0; i < width; i++)
374 #ifdef liftS
375         b1[i] -= (W_BM * (b0[i] + b2[i]) + W_BO) >> W_BS;
376 #else
377         b1[i] = (16 * 4 * b1[i] - 4 * (b0[i] + b2[i]) + W_BO * 5 + (5 << 27)) /
378                 (5 * 16) - (1 << 23);
379 #endif
380 }
381
382 static void vertical_decompose97iL1(DWTELEM *b0, DWTELEM *b1, DWTELEM *b2,
383                                     int width)
384 {
385     int i;
386
387     for (i = 0; i < width; i++)
388         b1[i] += (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS;
389 }
390
391 static void spatial_decompose97i(DWTELEM *buffer, int width, int height,
392                                  int stride)
393 {
394     int y;
395     DWTELEM *b0 = buffer + mirror(-4 - 1, height - 1) * stride;
396     DWTELEM *b1 = buffer + mirror(-4,     height - 1) * stride;
397     DWTELEM *b2 = buffer + mirror(-4 + 1, height - 1) * stride;
398     DWTELEM *b3 = buffer + mirror(-4 + 2, height - 1) * stride;
399
400     for (y = -4; y < height; y += 2) {
401         DWTELEM *b4 = buffer + mirror(y + 3, height - 1) * stride;
402         DWTELEM *b5 = buffer + mirror(y + 4, height - 1) * stride;
403
404         if (y + 3 < (unsigned)height)
405             horizontal_decompose97i(b4, width);
406         if (y + 4 < (unsigned)height)
407             horizontal_decompose97i(b5, width);
408
409         if (y + 3 < (unsigned)height)
410             vertical_decompose97iH0(b3, b4, b5, width);
411         if (y + 2 < (unsigned)height)
412             vertical_decompose97iL0(b2, b3, b4, width);
413         if (y + 1 < (unsigned)height)
414             vertical_decompose97iH1(b1, b2, b3, width);
415         if (y + 0 < (unsigned)height)
416             vertical_decompose97iL1(b0, b1, b2, width);
417
418         b0 = b2;
419         b1 = b3;
420         b2 = b4;
421         b3 = b5;
422     }
423 }
424
425 void ff_spatial_dwt(DWTELEM *buffer, int width, int height, int stride,
426                     int type, int decomposition_count)
427 {
428     int level;
429
430     for (level = 0; level < decomposition_count; level++) {
431         switch (type) {
432         case DWT_97:
433             spatial_decompose97i(buffer,
434                                  width >> level, height >> level,
435                                  stride << level);
436             break;
437         case DWT_53:
438             spatial_decompose53i(buffer,
439                                  width >> level, height >> level,
440                                  stride << level);
441             break;
442         }
443     }
444 }
445
446 static void horizontal_compose53i(IDWTELEM *b, int width)
447 {
448     IDWTELEM temp[width];
449     const int width2 = width >> 1;
450     const int w2     = (width + 1) >> 1;
451     int x;
452
453     for (x = 0; x < width2; x++) {
454         temp[2 * x]     = b[x];
455         temp[2 * x + 1] = b[x + w2];
456     }
457     if (width & 1)
458         temp[2 * x] = b[x];
459
460     b[0] = temp[0] - ((temp[1] + 1) >> 1);
461     for (x = 2; x < width - 1; x += 2) {
462         b[x]     = temp[x]     - ((temp[x - 1] + temp[x + 1] + 2) >> 2);
463         b[x - 1] = temp[x - 1] + ((b[x - 2]    + b[x]        + 1) >> 1);
464     }
465     if (width & 1) {
466         b[x]     = temp[x]     - ((temp[x - 1]     + 1) >> 1);
467         b[x - 1] = temp[x - 1] + ((b[x - 2] + b[x] + 1) >> 1);
468     } else
469         b[x - 1] = temp[x - 1] + b[x - 2];
470 }
471
472 static void vertical_compose53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
473                                   int width)
474 {
475     int i;
476
477     for (i = 0; i < width; i++)
478         b1[i] += (b0[i] + b2[i]) >> 1;
479 }
480
481 static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
482                                   int width)
483 {
484     int i;
485
486     for (i = 0; i < width; i++)
487         b1[i] -= (b0[i] + b2[i] + 2) >> 2;
488 }
489
490 static void spatial_compose53i_buffered_init(DWTCompose *cs, slice_buffer *sb,
491                                              int height, int stride_line)
492 {
493     cs->b0 = slice_buffer_get_line(sb,
494                                    mirror(-1 - 1, height - 1) * stride_line);
495     cs->b1 = slice_buffer_get_line(sb, mirror(-1, height - 1) * stride_line);
496     cs->y  = -1;
497 }
498
499 static void spatial_compose53i_init(DWTCompose *cs, IDWTELEM *buffer,
500                                     int height, int stride)
501 {
502     cs->b0 = buffer + mirror(-1 - 1, height - 1) * stride;
503     cs->b1 = buffer + mirror(-1,     height - 1) * stride;
504     cs->y  = -1;
505 }
506
507 static void spatial_compose53i_dy_buffered(DWTCompose *cs, slice_buffer *sb,
508                                            int width, int height,
509                                            int stride_line)
510 {
511     int y = cs->y;
512
513     IDWTELEM *b0 = cs->b0;
514     IDWTELEM *b1 = cs->b1;
515     IDWTELEM *b2 = slice_buffer_get_line(sb,
516                                          mirror(y + 1, height - 1) *
517                                          stride_line);
518     IDWTELEM *b3 = slice_buffer_get_line(sb,
519                                          mirror(y + 2, height - 1) *
520                                          stride_line);
521
522     if (y + 1 < (unsigned)height && y < (unsigned)height) {
523         int x;
524
525         for (x = 0; x < width; x++) {
526             b2[x] -= (b1[x] + b3[x] + 2) >> 2;
527             b1[x] += (b0[x] + b2[x])     >> 1;
528         }
529     } else {
530         if (y + 1 < (unsigned)height)
531             vertical_compose53iL0(b1, b2, b3, width);
532         if (y + 0 < (unsigned)height)
533             vertical_compose53iH0(b0, b1, b2, width);
534     }
535
536     if (y - 1 < (unsigned)height)
537         horizontal_compose53i(b0, width);
538     if (y + 0 < (unsigned)height)
539         horizontal_compose53i(b1, width);
540
541     cs->b0  = b2;
542     cs->b1  = b3;
543     cs->y  += 2;
544 }
545
546 static void spatial_compose53i_dy(DWTCompose *cs, IDWTELEM *buffer, int width,
547                                   int height, int stride)
548 {
549     int y        = cs->y;
550     IDWTELEM *b0 = cs->b0;
551     IDWTELEM *b1 = cs->b1;
552     IDWTELEM *b2 = buffer + mirror(y + 1, height - 1) * stride;
553     IDWTELEM *b3 = buffer + mirror(y + 2, height - 1) * stride;
554
555     if (y + 1 < (unsigned)height)
556         vertical_compose53iL0(b1, b2, b3, width);
557     if (y + 0 < (unsigned)height)
558         vertical_compose53iH0(b0, b1, b2, width);
559
560     if (y - 1 < (unsigned)height)
561         horizontal_compose53i(b0, width);
562     if (y + 0 < (unsigned)height)
563         horizontal_compose53i(b1, width);
564
565     cs->b0  = b2;
566     cs->b1  = b3;
567     cs->y  += 2;
568 }
569
570 static void av_unused spatial_compose53i(IDWTELEM *buffer, int width,
571                                          int height, int stride)
572 {
573     DWTCompose cs;
574     spatial_compose53i_init(&cs, buffer, height, stride);
575     while (cs.y <= height)
576         spatial_compose53i_dy(&cs, buffer, width, height, stride);
577 }
578
579 void ff_snow_horizontal_compose97i(IDWTELEM *b, int width)
580 {
581     IDWTELEM temp[width];
582     const int w2 = (width + 1) >> 1;
583
584 #if 0 //maybe more understadable but slower
585     inv_lift(temp,     b,      b + w2, 2, 1, 1, width, W_DM, W_DO, W_DS, 0, 1);
586     inv_lift(temp + 1, b + w2, temp,   2, 1, 2, width, W_CM, W_CO, W_CS, 1, 1);
587
588     inv_liftS(b,    temp,     temp + 1, 2, 2, 2, width, W_BM, W_BO, W_BS, 0, 1);
589     inv_lift(b + 1, temp + 1, b,        2, 2, 2, width, W_AM, W_AO, W_AS, 1, 0);
590 #else
591     int x;
592     temp[0] = b[0] - ((3 * b[w2] + 2) >> 2);
593     for (x = 1; x < (width >> 1); x++) {
594         temp[2 * x]     = b[x] - ((3 * (b[x + w2 - 1] + b[x + w2]) + 4) >> 3);
595         temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x];
596     }
597     if (width & 1) {
598         temp[2 * x]     = b[x] - ((3 * b[x + w2 - 1] + 2) >> 2);
599         temp[2 * x - 1] = b[x + w2 - 1] - temp[2 * x - 2] - temp[2 * x];
600     } else
601         temp[2 * x - 1] = b[x + w2 - 1] - 2 * temp[2 * x - 2];
602
603     b[0] = temp[0] + ((2 * temp[0] + temp[1] + 4) >> 3);
604     for (x = 2; x < width - 1; x += 2) {
605         b[x]     = temp[x] + ((4 * temp[x] + temp[x - 1] + temp[x + 1] + 8) >> 4);
606         b[x - 1] = temp[x - 1] + ((3 * (b[x - 2] + b[x])) >> 1);
607     }
608     if (width & 1) {
609         b[x]     = temp[x] + ((2 * temp[x] + temp[x - 1] + 4) >> 3);
610         b[x - 1] = temp[x - 1] + ((3 * (b[x - 2] + b[x])) >> 1);
611     } else
612         b[x - 1] = temp[x - 1] + 3 * b[x - 2];
613 #endif
614 }
615
616 static void vertical_compose97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
617                                   int width)
618 {
619     int i;
620
621     for (i = 0; i < width; i++)
622         b1[i] += (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS;
623 }
624
625 static void vertical_compose97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
626                                   int width)
627 {
628     int i;
629
630     for (i = 0; i < width; i++)
631         b1[i] -= (W_CM * (b0[i] + b2[i]) + W_CO) >> W_CS;
632 }
633
634 static void vertical_compose97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
635                                   int width)
636 {
637     int i;
638
639     for (i = 0; i < width; i++)
640 #ifdef liftS
641         b1[i] += (W_BM * (b0[i] + b2[i]) + W_BO) >> W_BS;
642 #else
643         b1[i] += (W_BM * (b0[i] + b2[i]) + 4 * b1[i] + W_BO) >> W_BS;
644 #endif
645 }
646
647 static void vertical_compose97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
648                                   int width)
649 {
650     int i;
651
652     for (i = 0; i < width; i++)
653         b1[i] -= (W_DM * (b0[i] + b2[i]) + W_DO) >> W_DS;
654 }
655
656 void ff_snow_vertical_compose97i(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
657                                  IDWTELEM *b3, IDWTELEM *b4, IDWTELEM *b5,
658                                  int width)
659 {
660     int i;
661
662     for (i = 0; i < width; i++) {
663         b4[i] -= (W_DM * (b3[i] + b5[i]) + W_DO) >> W_DS;
664         b3[i] -= (W_CM * (b2[i] + b4[i]) + W_CO) >> W_CS;
665 #ifdef liftS
666         b2[i] += (W_BM * (b1[i] + b3[i]) + W_BO) >> W_BS;
667 #else
668         b2[i] += (W_BM * (b1[i] + b3[i]) + 4 * b2[i] + W_BO) >> W_BS;
669 #endif
670         b1[i] += (W_AM * (b0[i] + b2[i]) + W_AO) >> W_AS;
671     }
672 }
673
674 static void spatial_compose97i_buffered_init(DWTCompose *cs, slice_buffer *sb,
675                                              int height, int stride_line)
676 {
677     cs->b0 = slice_buffer_get_line(sb, mirror(-3 - 1, height - 1) * stride_line);
678     cs->b1 = slice_buffer_get_line(sb, mirror(-3,     height - 1) * stride_line);
679     cs->b2 = slice_buffer_get_line(sb, mirror(-3 + 1, height - 1) * stride_line);
680     cs->b3 = slice_buffer_get_line(sb, mirror(-3 + 2, height - 1) * stride_line);
681     cs->y  = -3;
682 }
683
684 static void spatial_compose97i_init(DWTCompose *cs, IDWTELEM *buffer, int height,
685                                     int stride)
686 {
687     cs->b0 = buffer + mirror(-3 - 1, height - 1) * stride;
688     cs->b1 = buffer + mirror(-3,     height - 1) * stride;
689     cs->b2 = buffer + mirror(-3 + 1, height - 1) * stride;
690     cs->b3 = buffer + mirror(-3 + 2, height - 1) * stride;
691     cs->y  = -3;
692 }
693
694 static void spatial_compose97i_dy_buffered(DWTContext *dsp, DWTCompose *cs,
695                                            slice_buffer *sb, int width,
696                                            int height, int stride_line)
697 {
698     int y = cs->y;
699
700     IDWTELEM *b0 = cs->b0;
701     IDWTELEM *b1 = cs->b1;
702     IDWTELEM *b2 = cs->b2;
703     IDWTELEM *b3 = cs->b3;
704     IDWTELEM *b4 = slice_buffer_get_line(sb,
705                                          mirror(y + 3, height - 1) *
706                                          stride_line);
707     IDWTELEM *b5 = slice_buffer_get_line(sb,
708                                          mirror(y + 4, height - 1) *
709                                          stride_line);
710
711     if (y > 0 && y + 4 < height) {
712         dsp->vertical_compose97i(b0, b1, b2, b3, b4, b5, width);
713     } else {
714         if (y + 3 < (unsigned)height)
715             vertical_compose97iL1(b3, b4, b5, width);
716         if (y + 2 < (unsigned)height)
717             vertical_compose97iH1(b2, b3, b4, width);
718         if (y + 1 < (unsigned)height)
719             vertical_compose97iL0(b1, b2, b3, width);
720         if (y + 0 < (unsigned)height)
721             vertical_compose97iH0(b0, b1, b2, width);
722     }
723
724     if (y - 1 < (unsigned)height)
725         dsp->horizontal_compose97i(b0, width);
726     if (y + 0 < (unsigned)height)
727         dsp->horizontal_compose97i(b1, width);
728
729     cs->b0  = b2;
730     cs->b1  = b3;
731     cs->b2  = b4;
732     cs->b3  = b5;
733     cs->y  += 2;
734 }
735
736 static void spatial_compose97i_dy(DWTCompose *cs, IDWTELEM *buffer, int width,
737                                   int height, int stride)
738 {
739     int y        = cs->y;
740     IDWTELEM *b0 = cs->b0;
741     IDWTELEM *b1 = cs->b1;
742     IDWTELEM *b2 = cs->b2;
743     IDWTELEM *b3 = cs->b3;
744     IDWTELEM *b4 = buffer + mirror(y + 3, height - 1) * stride;
745     IDWTELEM *b5 = buffer + mirror(y + 4, height - 1) * stride;
746
747     if (y + 3 < (unsigned)height)
748         vertical_compose97iL1(b3, b4, b5, width);
749     if (y + 2 < (unsigned)height)
750         vertical_compose97iH1(b2, b3, b4, width);
751     if (y + 1 < (unsigned)height)
752         vertical_compose97iL0(b1, b2, b3, width);
753     if (y + 0 < (unsigned)height)
754         vertical_compose97iH0(b0, b1, b2, width);
755
756     if (y - 1 < (unsigned)height)
757         ff_snow_horizontal_compose97i(b0, width);
758     if (y + 0 < (unsigned)height)
759         ff_snow_horizontal_compose97i(b1, width);
760
761     cs->b0  = b2;
762     cs->b1  = b3;
763     cs->b2  = b4;
764     cs->b3  = b5;
765     cs->y  += 2;
766 }
767
768 static void av_unused spatial_compose97i(IDWTELEM *buffer, int width,
769                                          int height, int stride)
770 {
771     DWTCompose cs;
772     spatial_compose97i_init(&cs, buffer, height, stride);
773     while (cs.y <= height)
774         spatial_compose97i_dy(&cs, buffer, width, height, stride);
775 }
776
777 void ff_spatial_idwt_buffered_init(DWTCompose *cs, slice_buffer *sb, int width,
778                                    int height, int stride_line, int type,
779                                    int decomposition_count)
780 {
781     int level;
782     for (level = decomposition_count - 1; level >= 0; level--) {
783         switch (type) {
784         case DWT_97:
785             spatial_compose97i_buffered_init(cs + level, sb, height >> level,
786                                              stride_line << level);
787             break;
788         case DWT_53:
789             spatial_compose53i_buffered_init(cs + level, sb, height >> level,
790                                              stride_line << level);
791             break;
792         }
793     }
794 }
795
796 void ff_spatial_idwt_buffered_slice(DWTContext *dsp, DWTCompose *cs,
797                                     slice_buffer *slice_buf, int width,
798                                     int height, int stride_line, int type,
799                                     int decomposition_count, int y)
800 {
801     const int support = type == 1 ? 3 : 5;
802     int level;
803     if (type == 2)
804         return;
805
806     for (level = decomposition_count - 1; level >= 0; level--)
807         while (cs[level].y <= FFMIN((y >> level) + support, height >> level)) {
808             switch (type) {
809             case DWT_97:
810                 spatial_compose97i_dy_buffered(dsp, cs + level, slice_buf,
811                                                width >> level,
812                                                height >> level,
813                                                stride_line << level);
814                 break;
815             case DWT_53:
816                 spatial_compose53i_dy_buffered(cs + level, slice_buf,
817                                                width >> level,
818                                                height >> level,
819                                                stride_line << level);
820                 break;
821             }
822         }
823 }
824
825 static void ff_spatial_idwt_init(DWTCompose *cs, IDWTELEM *buffer, int width,
826                                  int height, int stride, int type,
827                                  int decomposition_count)
828 {
829     int level;
830     for (level = decomposition_count - 1; level >= 0; level--) {
831         switch (type) {
832         case DWT_97:
833             spatial_compose97i_init(cs + level, buffer, height >> level,
834                                     stride << level);
835             break;
836         case DWT_53:
837             spatial_compose53i_init(cs + level, buffer, height >> level,
838                                     stride << level);
839             break;
840         }
841     }
842 }
843
844 static void ff_spatial_idwt_slice(DWTCompose *cs, IDWTELEM *buffer, int width,
845                                   int height, int stride, int type,
846                                   int decomposition_count, int y)
847 {
848     const int support = type == 1 ? 3 : 5;
849     int level;
850     if (type == 2)
851         return;
852
853     for (level = decomposition_count - 1; level >= 0; level--)
854         while (cs[level].y <= FFMIN((y >> level) + support, height >> level)) {
855             switch (type) {
856             case DWT_97:
857                 spatial_compose97i_dy(cs + level, buffer, width >> level,
858                                       height >> level, stride << level);
859                 break;
860             case DWT_53:
861                 spatial_compose53i_dy(cs + level, buffer, width >> level,
862                                       height >> level, stride << level);
863                 break;
864             }
865         }
866 }
867
868 void ff_spatial_idwt(IDWTELEM *buffer, int width, int height, int stride,
869                      int type, int decomposition_count)
870 {
871     DWTCompose cs[MAX_DECOMPOSITIONS];
872     int y;
873     ff_spatial_idwt_init(cs, buffer, width, height, stride, type,
874                          decomposition_count);
875     for (y = 0; y < height; y += 4)
876         ff_spatial_idwt_slice(cs, buffer, width, height, stride, type,
877                               decomposition_count, y);
878 }
879
880 static inline int w_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size,
881                       int w, int h, int type)
882 {
883     int s, i, j;
884     const int dec_count = w == 8 ? 3 : 4;
885     int tmp[32 * 32];
886     int level, ori;
887     static const int scale[2][2][4][4] = {
888         {
889             { // 9/7 8x8 dec=3
890                 { 268, 239, 239, 213 },
891                 { 0,   224, 224, 152 },
892                 { 0,   135, 135, 110 },
893             },
894             { // 9/7 16x16 or 32x32 dec=4
895                 { 344, 310, 310, 280 },
896                 { 0,   320, 320, 228 },
897                 { 0,   175, 175, 136 },
898                 { 0,   129, 129, 102 },
899             }
900         },
901         {
902             { // 5/3 8x8 dec=3
903                 { 275, 245, 245, 218 },
904                 { 0,   230, 230, 156 },
905                 { 0,   138, 138, 113 },
906             },
907             { // 5/3 16x16 or 32x32 dec=4
908                 { 352, 317, 317, 286 },
909                 { 0,   328, 328, 233 },
910                 { 0,   180, 180, 140 },
911                 { 0,   132, 132, 105 },
912             }
913         }
914     };
915
916     for (i = 0; i < h; i++) {
917         for (j = 0; j < w; j += 4) {
918             tmp[32 * i + j + 0] = (pix1[j + 0] - pix2[j + 0]) << 4;
919             tmp[32 * i + j + 1] = (pix1[j + 1] - pix2[j + 1]) << 4;
920             tmp[32 * i + j + 2] = (pix1[j + 2] - pix2[j + 2]) << 4;
921             tmp[32 * i + j + 3] = (pix1[j + 3] - pix2[j + 3]) << 4;
922         }
923         pix1 += line_size;
924         pix2 += line_size;
925     }
926
927     ff_spatial_dwt(tmp, w, h, 32, type, dec_count);
928
929     s = 0;
930     assert(w == h);
931     for (level = 0; level < dec_count; level++)
932         for (ori = level ? 1 : 0; ori < 4; ori++) {
933             int size   = w >> (dec_count - level);
934             int sx     = (ori & 1) ? size : 0;
935             int stride = 32 << (dec_count - level);
936             int sy     = (ori & 2) ? stride >> 1 : 0;
937
938             for (i = 0; i < size; i++)
939                 for (j = 0; j < size; j++) {
940                     int v = tmp[sx + sy + i * stride + j] *
941                             scale[type][dec_count - 3][level][ori];
942                     s += FFABS(v);
943                 }
944         }
945     assert(s >= 0);
946     return s >> 9;
947 }
948
949 static int w53_8_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
950 {
951     return w_c(v, pix1, pix2, line_size, 8, h, 1);
952 }
953
954 static int w97_8_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
955 {
956     return w_c(v, pix1, pix2, line_size, 8, h, 0);
957 }
958
959 static int w53_16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
960 {
961     return w_c(v, pix1, pix2, line_size, 16, h, 1);
962 }
963
964 static int w97_16_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
965 {
966     return w_c(v, pix1, pix2, line_size, 16, h, 0);
967 }
968
969 int ff_w53_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
970 {
971     return w_c(v, pix1, pix2, line_size, 32, h, 1);
972 }
973
974 int ff_w97_32_c(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, int h)
975 {
976     return w_c(v, pix1, pix2, line_size, 32, h, 0);
977 }
978
979 void ff_dsputil_init_dwt(DSPContext *c)
980 {
981     c->w53[0] = w53_16_c;
982     c->w53[1] = w53_8_c;
983     c->w97[0] = w97_16_c;
984     c->w97[1] = w97_8_c;
985 }
986
987 void ff_dwt_init(DWTContext *c)
988 {
989     c->vertical_compose97i   = ff_snow_vertical_compose97i;
990     c->horizontal_compose97i = ff_snow_horizontal_compose97i;
991     c->inner_add_yblock      = ff_snow_inner_add_yblock;
992
993     if (HAVE_MMX)
994         ff_dwt_init_x86(c);
995 }