1/*
2 * Copyright (C) 2004-2010 Michael Niedermayer <michaelni@gmx.at>
3 * Copyright (C) 2008 David Conrad
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavutil/attributes.h"
23#include "libavutil/avassert.h"
24#include "libavutil/common.h"
25#include "dsputil.h"
26#include "dirac_dwt.h"
27#include "libavcodec/x86/dirac_dwt.h"
28
29
30static inline int mirror(int v, int m)
31{
32    while ((unsigned)v > (unsigned)m) {
33        v = -v;
34        if (v < 0)
35            v += 2 * m;
36    }
37    return v;
38}
39
40static void vertical_compose53iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
41                                  int width)
42{
43    int i;
44
45    for (i = 0; i < width; i++)
46        b1[i] -= (b0[i] + b2[i] + 2) >> 2;
47}
48
49
50static av_always_inline
51void interleave(IDWTELEM *dst, IDWTELEM *src0, IDWTELEM *src1, int w2, int add, int shift)
52{
53    int i;
54    for (i = 0; i < w2; i++) {
55        dst[2*i  ] = (src0[i] + add) >> shift;
56        dst[2*i+1] = (src1[i] + add) >> shift;
57    }
58}
59
60static void horizontal_compose_dirac53i(IDWTELEM *b, IDWTELEM *temp, int w)
61{
62    const int w2 = w >> 1;
63    int x;
64
65    temp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
66    for (x = 1; x < w2; x++) {
67        temp[x     ] = COMPOSE_53iL0     (b[x+w2-1], b[x     ], b[x+w2]);
68        temp[x+w2-1] = COMPOSE_DIRAC53iH0(temp[x-1], b[x+w2-1], temp[x]);
69    }
70    temp[w-1] = COMPOSE_DIRAC53iH0(temp[w2-1], b[w-1], temp[w2-1]);
71
72    interleave(b, temp, temp+w2, w2, 1, 1);
73}
74
75static void horizontal_compose_dd97i(IDWTELEM *b, IDWTELEM *tmp, int w)
76{
77    const int w2 = w >> 1;
78    int x;
79
80    tmp[0] = COMPOSE_53iL0(b[w2], b[0], b[w2]);
81    for (x = 1; x < w2; x++)
82        tmp[x] = COMPOSE_53iL0(b[x+w2-1], b[x], b[x+w2]);
83
84    // extend the edges
85    tmp[-1]   = tmp[0];
86    tmp[w2+1] = tmp[w2] = tmp[w2-1];
87
88    for (x = 0; x < w2; x++) {
89        b[2*x  ] = (tmp[x] + 1)>>1;
90        b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
91    }
92}
93
94static void horizontal_compose_dd137i(IDWTELEM *b, IDWTELEM *tmp, int w)
95{
96    const int w2 = w >> 1;
97    int x;
98
99    tmp[0] = COMPOSE_DD137iL0(b[w2], b[w2], b[0], b[w2  ], b[w2+1]);
100    tmp[1] = COMPOSE_DD137iL0(b[w2], b[w2], b[1], b[w2+1], b[w2+2]);
101    for (x = 2; x < w2-1; x++)
102        tmp[x] = COMPOSE_DD137iL0(b[x+w2-2], b[x+w2-1], b[x], b[x+w2], b[x+w2+1]);
103    tmp[w2-1] = COMPOSE_DD137iL0(b[w-3], b[w-2], b[w2-1], b[w-1], b[w-1]);
104
105    // extend the edges
106    tmp[-1]   = tmp[0];
107    tmp[w2+1] = tmp[w2] = tmp[w2-1];
108
109    for (x = 0; x < w2; x++) {
110        b[2*x  ] = (tmp[x] + 1)>>1;
111        b[2*x+1] = (COMPOSE_DD97iH0(tmp[x-1], tmp[x], b[x+w2], tmp[x+1], tmp[x+2]) + 1)>>1;
112    }
113}
114
115static av_always_inline
116void horizontal_compose_haari(IDWTELEM *b, IDWTELEM *temp, int w, int shift)
117{
118    const int w2 = w >> 1;
119    int x;
120
121    for (x = 0; x < w2; x++) {
122        temp[x   ] = COMPOSE_HAARiL0(b[x   ], b[x+w2]);
123        temp[x+w2] = COMPOSE_HAARiH0(b[x+w2], temp[x]);
124    }
125
126    interleave(b, temp, temp+w2, w2, shift, shift);
127}
128
129static void horizontal_compose_haar0i(IDWTELEM *b, IDWTELEM *temp, int w)
130{
131    horizontal_compose_haari(b, temp, w, 0);
132}
133
134static void horizontal_compose_haar1i(IDWTELEM *b, IDWTELEM *temp, int w)
135{
136    horizontal_compose_haari(b, temp, w, 1);
137}
138
139static void horizontal_compose_fidelityi(IDWTELEM *b, IDWTELEM *tmp, int w)
140{
141    const int w2 = w >> 1;
142    int i, x;
143    IDWTELEM v[8];
144
145    for (x = 0; x < w2; x++) {
146        for (i = 0; i < 8; i++)
147            v[i] = b[av_clip(x-3+i, 0, w2-1)];
148        tmp[x] = COMPOSE_FIDELITYiH0(v[0], v[1], v[2], v[3], b[x+w2], v[4], v[5], v[6], v[7]);
149    }
150
151    for (x = 0; x < w2; x++) {
152        for (i = 0; i < 8; i++)
153            v[i] = tmp[av_clip(x-4+i, 0, w2-1)];
154        tmp[x+w2] = COMPOSE_FIDELITYiL0(v[0], v[1], v[2], v[3], b[x], v[4], v[5], v[6], v[7]);
155    }
156
157    interleave(b, tmp+w2, tmp, w2, 0, 0);
158}
159
160static void horizontal_compose_daub97i(IDWTELEM *b, IDWTELEM *temp, int w)
161{
162    const int w2 = w >> 1;
163    int x, b0, b1, b2;
164
165    temp[0] = COMPOSE_DAUB97iL1(b[w2], b[0], b[w2]);
166    for (x = 1; x < w2; x++) {
167        temp[x     ] = COMPOSE_DAUB97iL1(b[x+w2-1], b[x     ], b[x+w2]);
168        temp[x+w2-1] = COMPOSE_DAUB97iH1(temp[x-1], b[x+w2-1], temp[x]);
169    }
170    temp[w-1] = COMPOSE_DAUB97iH1(temp[w2-1], b[w-1], temp[w2-1]);
171
172    // second stage combined with interleave and shift
173    b0 = b2 = COMPOSE_DAUB97iL0(temp[w2], temp[0], temp[w2]);
174    b[0] = (b0 + 1) >> 1;
175    for (x = 1; x < w2; x++) {
176        b2 = COMPOSE_DAUB97iL0(temp[x+w2-1], temp[x     ], temp[x+w2]);
177        b1 = COMPOSE_DAUB97iH0(          b0, temp[x+w2-1], b2        );
178        b[2*x-1] = (b1 + 1) >> 1;
179        b[2*x  ] = (b2 + 1) >> 1;
180        b0 = b2;
181    }
182    b[w-1] = (COMPOSE_DAUB97iH0(b2, temp[w-1], b2) + 1) >> 1;
183}
184
185static void vertical_compose_dirac53iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
186{
187    int i;
188
189    for(i=0; i<width; i++){
190        b1[i] = COMPOSE_DIRAC53iH0(b0[i], b1[i], b2[i]);
191    }
192}
193
194static void vertical_compose_dd97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
195                                  IDWTELEM *b3, IDWTELEM *b4, int width)
196{
197    int i;
198
199    for(i=0; i<width; i++){
200        b2[i] = COMPOSE_DD97iH0(b0[i], b1[i], b2[i], b3[i], b4[i]);
201    }
202}
203
204static void vertical_compose_dd137iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2,
205                                      IDWTELEM *b3, IDWTELEM *b4, int width)
206{
207    int i;
208
209    for(i=0; i<width; i++){
210        b2[i] = COMPOSE_DD137iL0(b0[i], b1[i], b2[i], b3[i], b4[i]);
211    }
212}
213
214static void vertical_compose_haar(IDWTELEM *b0, IDWTELEM *b1, int width)
215{
216    int i;
217
218    for (i = 0; i < width; i++) {
219        b0[i] = COMPOSE_HAARiL0(b0[i], b1[i]);
220        b1[i] = COMPOSE_HAARiH0(b1[i], b0[i]);
221    }
222}
223
224static void vertical_compose_fidelityiH0(IDWTELEM *dst, IDWTELEM *b[8], int width)
225{
226    int i;
227
228    for(i=0; i<width; i++){
229        dst[i] = COMPOSE_FIDELITYiH0(b[0][i], b[1][i], b[2][i], b[3][i], dst[i], b[4][i], b[5][i], b[6][i], b[7][i]);
230    }
231}
232
233static void vertical_compose_fidelityiL0(IDWTELEM *dst, IDWTELEM *b[8], int width)
234{
235    int i;
236
237    for(i=0; i<width; i++){
238        dst[i] = COMPOSE_FIDELITYiL0(b[0][i], b[1][i], b[2][i], b[3][i], dst[i], b[4][i], b[5][i], b[6][i], b[7][i]);
239    }
240}
241
242static void vertical_compose_daub97iH0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
243{
244    int i;
245
246    for(i=0; i<width; i++){
247        b1[i] = COMPOSE_DAUB97iH0(b0[i], b1[i], b2[i]);
248    }
249}
250
251static void vertical_compose_daub97iH1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
252{
253    int i;
254
255    for(i=0; i<width; i++){
256        b1[i] = COMPOSE_DAUB97iH1(b0[i], b1[i], b2[i]);
257    }
258}
259
260static void vertical_compose_daub97iL0(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
261{
262    int i;
263
264    for(i=0; i<width; i++){
265        b1[i] = COMPOSE_DAUB97iL0(b0[i], b1[i], b2[i]);
266    }
267}
268
269static void vertical_compose_daub97iL1(IDWTELEM *b0, IDWTELEM *b1, IDWTELEM *b2, int width)
270{
271    int i;
272
273    for(i=0; i<width; i++){
274        b1[i] = COMPOSE_DAUB97iL1(b0[i], b1[i], b2[i]);
275    }
276}
277
278
279static void spatial_compose_dd97i_dy(DWTContext *d, int level, int width, int height, int stride)
280{
281    vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
282    vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
283    DWTCompose *cs = d->cs + level;
284
285    int i, y = cs->y;
286    IDWTELEM *b[8];
287    for (i = 0; i < 6; i++)
288        b[i] = cs->b[i];
289    b[6] = d->buffer + av_clip(y+5, 0, height-2)*stride;
290    b[7] = d->buffer + av_clip(y+6, 1, height-1)*stride;
291
292        if(y+5<(unsigned)height) vertical_compose_l0(      b[5], b[6], b[7],       width);
293        if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
294
295        if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
296        if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
297
298    for (i = 0; i < 6; i++)
299        cs->b[i] = b[i+2];
300    cs->y += 2;
301}
302
303static void spatial_compose_dirac53i_dy(DWTContext *d, int level, int width, int height, int stride)
304{
305    vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
306    vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
307    DWTCompose *cs = d->cs + level;
308
309    int y= cs->y;
310    IDWTELEM *b[4] = { cs->b[0], cs->b[1] };
311    b[2] = d->buffer + mirror(y+1, height-1)*stride;
312    b[3] = d->buffer + mirror(y+2, height-1)*stride;
313
314        if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
315        if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
316
317        if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
318        if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
319
320    cs->b[0] = b[2];
321    cs->b[1] = b[3];
322    cs->y += 2;
323}
324
325
326static void spatial_compose_dd137i_dy(DWTContext *d, int level, int width, int height, int stride)
327{
328    vertical_compose_5tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
329    vertical_compose_5tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
330    DWTCompose *cs = d->cs + level;
331
332    int i, y = cs->y;
333    IDWTELEM *b[10];
334    for (i = 0; i < 8; i++)
335        b[i] = cs->b[i];
336    b[8] = d->buffer + av_clip(y+7, 0, height-2)*stride;
337    b[9] = d->buffer + av_clip(y+8, 1, height-1)*stride;
338
339        if(y+5<(unsigned)height) vertical_compose_l0(b[3], b[5], b[6], b[7], b[9], width);
340        if(y+1<(unsigned)height) vertical_compose_h0(b[0], b[2], b[3], b[4], b[6], width);
341
342        if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
343        if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
344
345    for (i = 0; i < 8; i++)
346        cs->b[i] = b[i+2];
347    cs->y += 2;
348}
349
350// haar makes the assumption that height is even (always true for dirac)
351static void spatial_compose_haari_dy(DWTContext *d, int level, int width, int height, int stride)
352{
353    vertical_compose_2tap vertical_compose = (void*)d->vertical_compose;
354    int y = d->cs[level].y;
355    IDWTELEM *b0 = d->buffer + (y-1)*stride;
356    IDWTELEM *b1 = d->buffer + (y  )*stride;
357
358    vertical_compose(b0, b1, width);
359    d->horizontal_compose(b0, d->temp, width);
360    d->horizontal_compose(b1, d->temp, width);
361
362    d->cs[level].y += 2;
363}
364
365// Don't do sliced idwt for fidelity; the 9 tap filter makes it a bit annoying
366// Fortunately, this filter isn't used in practice.
367static void spatial_compose_fidelity(DWTContext *d, int level, int width, int height, int stride)
368{
369    vertical_compose_9tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
370    vertical_compose_9tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
371    int i, y;
372    IDWTELEM *b[8];
373
374    for (y = 1; y < height; y += 2) {
375        for (i = 0; i < 8; i++)
376            b[i] = d->buffer + av_clip((y-7 + 2*i), 0, height-2)*stride;
377        vertical_compose_h0(d->buffer + y*stride, b, width);
378    }
379
380    for (y = 0; y < height; y += 2) {
381        for (i = 0; i < 8; i++)
382            b[i] = d->buffer + av_clip((y-7 + 2*i), 1, height-1)*stride;
383        vertical_compose_l0(d->buffer + y*stride, b, width);
384    }
385
386    for (y = 0; y < height; y++)
387        d->horizontal_compose(d->buffer + y*stride, d->temp, width);
388
389    d->cs[level].y = height+1;
390}
391
392static void spatial_compose_daub97i_dy(DWTContext *d, int level, int width, int height, int stride)
393{
394    vertical_compose_3tap vertical_compose_l0 = (void*)d->vertical_compose_l0;
395    vertical_compose_3tap vertical_compose_h0 = (void*)d->vertical_compose_h0;
396    vertical_compose_3tap vertical_compose_l1 = (void*)d->vertical_compose_l1;
397    vertical_compose_3tap vertical_compose_h1 = (void*)d->vertical_compose_h1;
398    DWTCompose *cs = d->cs + level;
399
400    int i, y = cs->y;
401    IDWTELEM *b[6];
402    for (i = 0; i < 4; i++)
403        b[i] = cs->b[i];
404    b[4] = d->buffer + mirror(y+3, height-1)*stride;
405    b[5] = d->buffer + mirror(y+4, height-1)*stride;
406
407        if(y+3<(unsigned)height) vertical_compose_l1(b[3], b[4], b[5], width);
408        if(y+2<(unsigned)height) vertical_compose_h1(b[2], b[3], b[4], width);
409        if(y+1<(unsigned)height) vertical_compose_l0(b[1], b[2], b[3], width);
410        if(y+0<(unsigned)height) vertical_compose_h0(b[0], b[1], b[2], width);
411
412        if(y-1<(unsigned)height) d->horizontal_compose(b[0], d->temp, width);
413        if(y+0<(unsigned)height) d->horizontal_compose(b[1], d->temp, width);
414
415    for (i = 0; i < 4; i++)
416        cs->b[i] = b[i+2];
417    cs->y += 2;
418}
419
420
421static void spatial_compose97i_init2(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
422{
423    cs->b[0] = buffer + mirror(-3-1, height-1)*stride;
424    cs->b[1] = buffer + mirror(-3  , height-1)*stride;
425    cs->b[2] = buffer + mirror(-3+1, height-1)*stride;
426    cs->b[3] = buffer + mirror(-3+2, height-1)*stride;
427    cs->y = -3;
428}
429
430static void spatial_compose53i_init2(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
431{
432    cs->b[0] = buffer + mirror(-1-1, height-1)*stride;
433    cs->b[1] = buffer + mirror(-1  , height-1)*stride;
434    cs->y = -1;
435}
436
437static void spatial_compose_dd97i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
438{
439    cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
440    cs->b[1] = buffer + av_clip(-5  , 1, height-1)*stride;
441    cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
442    cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
443    cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
444    cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
445    cs->y = -5;
446}
447
448static void spatial_compose_dd137i_init(DWTCompose *cs, IDWTELEM *buffer, int height, int stride)
449{
450    cs->b[0] = buffer + av_clip(-5-1, 0, height-2)*stride;
451    cs->b[1] = buffer + av_clip(-5  , 1, height-1)*stride;
452    cs->b[2] = buffer + av_clip(-5+1, 0, height-2)*stride;
453    cs->b[3] = buffer + av_clip(-5+2, 1, height-1)*stride;
454    cs->b[4] = buffer + av_clip(-5+3, 0, height-2)*stride;
455    cs->b[5] = buffer + av_clip(-5+4, 1, height-1)*stride;
456    cs->b[6] = buffer + av_clip(-5+5, 0, height-2)*stride;
457    cs->b[7] = buffer + av_clip(-5+6, 1, height-1)*stride;
458    cs->y = -5;
459}
460
461int ff_spatial_idwt_init2(DWTContext *d, IDWTELEM *buffer, int width, int height,
462                          int stride, enum dwt_type type, int decomposition_count,
463                          IDWTELEM *temp)
464{
465    int level;
466
467    d->buffer = buffer;
468    d->width = width;
469    d->height = height;
470    d->stride = stride;
471    d->decomposition_count = decomposition_count;
472    d->temp = temp + 8;
473
474    for(level=decomposition_count-1; level>=0; level--){
475        int hl = height >> level;
476        int stride_l = stride << level;
477
478        switch(type){
479        case DWT_DIRAC_DD9_7:
480            spatial_compose_dd97i_init(d->cs+level, buffer, hl, stride_l);
481            break;
482        case DWT_DIRAC_LEGALL5_3:
483            spatial_compose53i_init2(d->cs+level, buffer, hl, stride_l);
484            break;
485        case DWT_DIRAC_DD13_7:
486            spatial_compose_dd137i_init(d->cs+level, buffer, hl, stride_l);
487            break;
488        case DWT_DIRAC_HAAR0:
489        case DWT_DIRAC_HAAR1:
490            d->cs[level].y = 1;
491            break;
492        case DWT_DIRAC_DAUB9_7:
493            spatial_compose97i_init2(d->cs+level, buffer, hl, stride_l);
494            break;
495        default:
496            d->cs[level].y = 0;
497            break;
498        }
499    }
500
501    switch (type) {
502    case DWT_DIRAC_DD9_7:
503        d->spatial_compose = spatial_compose_dd97i_dy;
504        d->vertical_compose_l0 = (void*)vertical_compose53iL0;
505        d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0;
506        d->horizontal_compose = horizontal_compose_dd97i;
507        d->support = 7;
508        break;
509    case DWT_DIRAC_LEGALL5_3:
510        d->spatial_compose = spatial_compose_dirac53i_dy;
511        d->vertical_compose_l0 = (void*)vertical_compose53iL0;
512        d->vertical_compose_h0 = (void*)vertical_compose_dirac53iH0;
513        d->horizontal_compose = horizontal_compose_dirac53i;
514        d->support = 3;
515        break;
516    case DWT_DIRAC_DD13_7:
517        d->spatial_compose = spatial_compose_dd137i_dy;
518        d->vertical_compose_l0 = (void*)vertical_compose_dd137iL0;
519        d->vertical_compose_h0 = (void*)vertical_compose_dd97iH0;
520        d->horizontal_compose = horizontal_compose_dd137i;
521        d->support = 7;
522        break;
523    case DWT_DIRAC_HAAR0:
524    case DWT_DIRAC_HAAR1:
525        d->spatial_compose = spatial_compose_haari_dy;
526        d->vertical_compose = (void*)vertical_compose_haar;
527        if (type == DWT_DIRAC_HAAR0)
528            d->horizontal_compose = horizontal_compose_haar0i;
529        else
530            d->horizontal_compose = horizontal_compose_haar1i;
531        d->support = 1;
532        break;
533    case DWT_DIRAC_FIDELITY:
534        d->spatial_compose = spatial_compose_fidelity;
535        d->vertical_compose_l0 = (void*)vertical_compose_fidelityiL0;
536        d->vertical_compose_h0 = (void*)vertical_compose_fidelityiH0;
537        d->horizontal_compose = horizontal_compose_fidelityi;
538        d->support = 0; // not really used
539        break;
540    case DWT_DIRAC_DAUB9_7:
541        d->spatial_compose = spatial_compose_daub97i_dy;
542        d->vertical_compose_l0 = (void*)vertical_compose_daub97iL0;
543        d->vertical_compose_h0 = (void*)vertical_compose_daub97iH0;
544        d->vertical_compose_l1 = (void*)vertical_compose_daub97iL1;
545        d->vertical_compose_h1 = (void*)vertical_compose_daub97iH1;
546        d->horizontal_compose = horizontal_compose_daub97i;
547        d->support = 5;
548        break;
549    default:
550        av_log(NULL, AV_LOG_ERROR, "Unknown wavelet type %d\n", type);
551        return -1;
552    }
553
554    if (HAVE_MMX) ff_spatial_idwt_init_mmx(d, type);
555
556    return 0;
557}
558
559void ff_spatial_idwt_slice2(DWTContext *d, int y)
560{
561    int level, support = d->support;
562
563    for (level = d->decomposition_count-1; level >= 0; level--) {
564        int wl = d->width  >> level;
565        int hl = d->height >> level;
566        int stride_l = d->stride << level;
567
568        while (d->cs[level].y <= FFMIN((y>>level)+support, hl))
569            d->spatial_compose(d, level, wl, hl, stride_l);
570    }
571}
572
573