1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Discrete wavelet transform
3cabdff1aSopenharmony_ci * Copyright (c) 2007 Kamil Nowosad
4cabdff1aSopenharmony_ci * Copyright (c) 2013 Nicolas Bertrand <nicoinattendu@gmail.com>
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci/**
24cabdff1aSopenharmony_ci * @file
25cabdff1aSopenharmony_ci * Discrete wavelet transform
26cabdff1aSopenharmony_ci */
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci#include "libavutil/error.h"
29cabdff1aSopenharmony_ci#include "libavutil/macros.h"
30cabdff1aSopenharmony_ci#include "libavutil/mem.h"
31cabdff1aSopenharmony_ci#include "jpeg2000dwt.h"
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci/* Defines for 9/7 DWT lifting parameters.
34cabdff1aSopenharmony_ci * Parameters are in float. */
35cabdff1aSopenharmony_ci#define F_LFTG_ALPHA  1.586134342059924f
36cabdff1aSopenharmony_ci#define F_LFTG_BETA   0.052980118572961f
37cabdff1aSopenharmony_ci#define F_LFTG_GAMMA  0.882911075530934f
38cabdff1aSopenharmony_ci#define F_LFTG_DELTA  0.443506852043971f
39cabdff1aSopenharmony_ci
40cabdff1aSopenharmony_ci/* Lifting parameters in integer format.
41cabdff1aSopenharmony_ci * Computed as param = (float param) * (1 << 16) */
42cabdff1aSopenharmony_ci#define I_LFTG_ALPHA  103949ll
43cabdff1aSopenharmony_ci#define I_LFTG_BETA     3472ll
44cabdff1aSopenharmony_ci#define I_LFTG_GAMMA   57862ll
45cabdff1aSopenharmony_ci#define I_LFTG_DELTA   29066ll
46cabdff1aSopenharmony_ci#define I_LFTG_K       80621ll
47cabdff1aSopenharmony_ci#define I_LFTG_X       53274ll
48cabdff1aSopenharmony_ci#define I_PRESHIFT 8
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_cistatic inline void extend53(int *p, int i0, int i1)
51cabdff1aSopenharmony_ci{
52cabdff1aSopenharmony_ci    p[i0 - 1] = p[i0 + 1];
53cabdff1aSopenharmony_ci    p[i1]     = p[i1 - 2];
54cabdff1aSopenharmony_ci    p[i0 - 2] = p[i0 + 2];
55cabdff1aSopenharmony_ci    p[i1 + 1] = p[i1 - 3];
56cabdff1aSopenharmony_ci}
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_cistatic inline void extend97_float(float *p, int i0, int i1)
59cabdff1aSopenharmony_ci{
60cabdff1aSopenharmony_ci    int i;
61cabdff1aSopenharmony_ci
62cabdff1aSopenharmony_ci    for (i = 1; i <= 4; i++) {
63cabdff1aSopenharmony_ci        p[i0 - i]     = p[i0 + i];
64cabdff1aSopenharmony_ci        p[i1 + i - 1] = p[i1 - i - 1];
65cabdff1aSopenharmony_ci    }
66cabdff1aSopenharmony_ci}
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_cistatic inline void extend97_int(int32_t *p, int i0, int i1)
69cabdff1aSopenharmony_ci{
70cabdff1aSopenharmony_ci    int i;
71cabdff1aSopenharmony_ci
72cabdff1aSopenharmony_ci    for (i = 1; i <= 4; i++) {
73cabdff1aSopenharmony_ci        p[i0 - i]     = p[i0 + i];
74cabdff1aSopenharmony_ci        p[i1 + i - 1] = p[i1 - i - 1];
75cabdff1aSopenharmony_ci    }
76cabdff1aSopenharmony_ci}
77cabdff1aSopenharmony_ci
78cabdff1aSopenharmony_cistatic void sd_1d53(int *p, int i0, int i1)
79cabdff1aSopenharmony_ci{
80cabdff1aSopenharmony_ci    int i;
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_ci    if (i1 <= i0 + 1) {
83cabdff1aSopenharmony_ci        if (i0 == 1)
84cabdff1aSopenharmony_ci            p[1] <<= 1;
85cabdff1aSopenharmony_ci        return;
86cabdff1aSopenharmony_ci    }
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci    extend53(p, i0, i1);
89cabdff1aSopenharmony_ci
90cabdff1aSopenharmony_ci    for (i = ((i0+1)>>1) - 1; i < (i1+1)>>1; i++)
91cabdff1aSopenharmony_ci        p[2*i+1] -= (p[2*i] + p[2*i+2]) >> 1;
92cabdff1aSopenharmony_ci    for (i = ((i0+1)>>1); i < (i1+1)>>1; i++)
93cabdff1aSopenharmony_ci        p[2*i] += (p[2*i-1] + p[2*i+1] + 2) >> 2;
94cabdff1aSopenharmony_ci}
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_cistatic void dwt_encode53(DWTContext *s, int *t)
97cabdff1aSopenharmony_ci{
98cabdff1aSopenharmony_ci    int lev,
99cabdff1aSopenharmony_ci        w = s->linelen[s->ndeclevels-1][0];
100cabdff1aSopenharmony_ci    int *line = s->i_linebuf;
101cabdff1aSopenharmony_ci    line += 3;
102cabdff1aSopenharmony_ci
103cabdff1aSopenharmony_ci    for (lev = s->ndeclevels-1; lev >= 0; lev--){
104cabdff1aSopenharmony_ci        int lh = s->linelen[lev][0],
105cabdff1aSopenharmony_ci            lv = s->linelen[lev][1],
106cabdff1aSopenharmony_ci            mh = s->mod[lev][0],
107cabdff1aSopenharmony_ci            mv = s->mod[lev][1],
108cabdff1aSopenharmony_ci            lp;
109cabdff1aSopenharmony_ci        int *l;
110cabdff1aSopenharmony_ci
111cabdff1aSopenharmony_ci        // VER_SD
112cabdff1aSopenharmony_ci        l = line + mv;
113cabdff1aSopenharmony_ci        for (lp = 0; lp < lh; lp++) {
114cabdff1aSopenharmony_ci            int i, j = 0;
115cabdff1aSopenharmony_ci
116cabdff1aSopenharmony_ci            for (i = 0; i < lv; i++)
117cabdff1aSopenharmony_ci                l[i] = t[w*i + lp];
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci            sd_1d53(line, mv, mv + lv);
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci            // copy back and deinterleave
122cabdff1aSopenharmony_ci            for (i =   mv; i < lv; i+=2, j++)
123cabdff1aSopenharmony_ci                t[w*j + lp] = l[i];
124cabdff1aSopenharmony_ci            for (i = 1-mv; i < lv; i+=2, j++)
125cabdff1aSopenharmony_ci                t[w*j + lp] = l[i];
126cabdff1aSopenharmony_ci        }
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci        // HOR_SD
129cabdff1aSopenharmony_ci        l = line + mh;
130cabdff1aSopenharmony_ci        for (lp = 0; lp < lv; lp++){
131cabdff1aSopenharmony_ci            int i, j = 0;
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_ci            for (i = 0; i < lh; i++)
134cabdff1aSopenharmony_ci                l[i] = t[w*lp + i];
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ci            sd_1d53(line, mh, mh + lh);
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci            // copy back and deinterleave
139cabdff1aSopenharmony_ci            for (i =   mh; i < lh; i+=2, j++)
140cabdff1aSopenharmony_ci                t[w*lp + j] = l[i];
141cabdff1aSopenharmony_ci            for (i = 1-mh; i < lh; i+=2, j++)
142cabdff1aSopenharmony_ci                t[w*lp + j] = l[i];
143cabdff1aSopenharmony_ci        }
144cabdff1aSopenharmony_ci    }
145cabdff1aSopenharmony_ci}
146cabdff1aSopenharmony_cistatic void sd_1d97_float(float *p, int i0, int i1)
147cabdff1aSopenharmony_ci{
148cabdff1aSopenharmony_ci    int i;
149cabdff1aSopenharmony_ci
150cabdff1aSopenharmony_ci    if (i1 <= i0 + 1) {
151cabdff1aSopenharmony_ci        if (i0 == 1)
152cabdff1aSopenharmony_ci            p[1] *= F_LFTG_X * 2;
153cabdff1aSopenharmony_ci        else
154cabdff1aSopenharmony_ci            p[0] *= F_LFTG_K;
155cabdff1aSopenharmony_ci        return;
156cabdff1aSopenharmony_ci    }
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci    extend97_float(p, i0, i1);
159cabdff1aSopenharmony_ci    i0++; i1++;
160cabdff1aSopenharmony_ci
161cabdff1aSopenharmony_ci    for (i = (i0>>1) - 2; i < (i1>>1) + 1; i++)
162cabdff1aSopenharmony_ci        p[2*i+1] -= 1.586134 * (p[2*i] + p[2*i+2]);
163cabdff1aSopenharmony_ci    for (i = (i0>>1) - 1; i < (i1>>1) + 1; i++)
164cabdff1aSopenharmony_ci        p[2*i] -= 0.052980 * (p[2*i-1] + p[2*i+1]);
165cabdff1aSopenharmony_ci    for (i = (i0>>1) - 1; i < (i1>>1); i++)
166cabdff1aSopenharmony_ci        p[2*i+1] += 0.882911 * (p[2*i] + p[2*i+2]);
167cabdff1aSopenharmony_ci    for (i = (i0>>1); i < (i1>>1); i++)
168cabdff1aSopenharmony_ci        p[2*i] += 0.443506 * (p[2*i-1] + p[2*i+1]);
169cabdff1aSopenharmony_ci}
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_cistatic void dwt_encode97_float(DWTContext *s, float *t)
172cabdff1aSopenharmony_ci{
173cabdff1aSopenharmony_ci    int lev,
174cabdff1aSopenharmony_ci        w = s->linelen[s->ndeclevels-1][0];
175cabdff1aSopenharmony_ci    float *line = s->f_linebuf;
176cabdff1aSopenharmony_ci    line += 5;
177cabdff1aSopenharmony_ci
178cabdff1aSopenharmony_ci    for (lev = s->ndeclevels-1; lev >= 0; lev--){
179cabdff1aSopenharmony_ci        int lh = s->linelen[lev][0],
180cabdff1aSopenharmony_ci            lv = s->linelen[lev][1],
181cabdff1aSopenharmony_ci            mh = s->mod[lev][0],
182cabdff1aSopenharmony_ci            mv = s->mod[lev][1],
183cabdff1aSopenharmony_ci            lp;
184cabdff1aSopenharmony_ci        float *l;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci        // HOR_SD
187cabdff1aSopenharmony_ci        l = line + mh;
188cabdff1aSopenharmony_ci        for (lp = 0; lp < lv; lp++){
189cabdff1aSopenharmony_ci            int i, j = 0;
190cabdff1aSopenharmony_ci
191cabdff1aSopenharmony_ci            for (i = 0; i < lh; i++)
192cabdff1aSopenharmony_ci                l[i] = t[w*lp + i];
193cabdff1aSopenharmony_ci
194cabdff1aSopenharmony_ci            sd_1d97_float(line, mh, mh + lh);
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_ci            // copy back and deinterleave
197cabdff1aSopenharmony_ci            for (i =   mh; i < lh; i+=2, j++)
198cabdff1aSopenharmony_ci                t[w*lp + j] = l[i];
199cabdff1aSopenharmony_ci            for (i = 1-mh; i < lh; i+=2, j++)
200cabdff1aSopenharmony_ci                t[w*lp + j] = l[i];
201cabdff1aSopenharmony_ci        }
202cabdff1aSopenharmony_ci
203cabdff1aSopenharmony_ci        // VER_SD
204cabdff1aSopenharmony_ci        l = line + mv;
205cabdff1aSopenharmony_ci        for (lp = 0; lp < lh; lp++) {
206cabdff1aSopenharmony_ci            int i, j = 0;
207cabdff1aSopenharmony_ci
208cabdff1aSopenharmony_ci            for (i = 0; i < lv; i++)
209cabdff1aSopenharmony_ci                l[i] = t[w*i + lp];
210cabdff1aSopenharmony_ci
211cabdff1aSopenharmony_ci            sd_1d97_float(line, mv, mv + lv);
212cabdff1aSopenharmony_ci
213cabdff1aSopenharmony_ci            // copy back and deinterleave
214cabdff1aSopenharmony_ci            for (i =   mv; i < lv; i+=2, j++)
215cabdff1aSopenharmony_ci                t[w*j + lp] = l[i];
216cabdff1aSopenharmony_ci            for (i = 1-mv; i < lv; i+=2, j++)
217cabdff1aSopenharmony_ci                t[w*j + lp] = l[i];
218cabdff1aSopenharmony_ci        }
219cabdff1aSopenharmony_ci    }
220cabdff1aSopenharmony_ci}
221cabdff1aSopenharmony_ci
222cabdff1aSopenharmony_cistatic void sd_1d97_int(int *p, int i0, int i1)
223cabdff1aSopenharmony_ci{
224cabdff1aSopenharmony_ci    int i;
225cabdff1aSopenharmony_ci
226cabdff1aSopenharmony_ci    if (i1 <= i0 + 1) {
227cabdff1aSopenharmony_ci        if (i0 == 1)
228cabdff1aSopenharmony_ci            p[1] = (p[1] * I_LFTG_X + (1<<14)) >> 15;
229cabdff1aSopenharmony_ci        else
230cabdff1aSopenharmony_ci            p[0] = (p[0] * I_LFTG_K + (1<<15)) >> 16;
231cabdff1aSopenharmony_ci        return;
232cabdff1aSopenharmony_ci    }
233cabdff1aSopenharmony_ci
234cabdff1aSopenharmony_ci    extend97_int(p, i0, i1);
235cabdff1aSopenharmony_ci    i0++; i1++;
236cabdff1aSopenharmony_ci
237cabdff1aSopenharmony_ci    for (i = (i0>>1) - 2; i < (i1>>1) + 1; i++)
238cabdff1aSopenharmony_ci        p[2 * i + 1] -= (I_LFTG_ALPHA * (p[2 * i]     + p[2 * i + 2]) + (1 << 15)) >> 16;
239cabdff1aSopenharmony_ci    for (i = (i0>>1) - 1; i < (i1>>1) + 1; i++)
240cabdff1aSopenharmony_ci        p[2 * i]     -= (I_LFTG_BETA  * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
241cabdff1aSopenharmony_ci    for (i = (i0>>1) - 1; i < (i1>>1); i++)
242cabdff1aSopenharmony_ci        p[2 * i + 1] += (I_LFTG_GAMMA * (p[2 * i]     + p[2 * i + 2]) + (1 << 15)) >> 16;
243cabdff1aSopenharmony_ci    for (i = (i0>>1); i < (i1>>1); i++)
244cabdff1aSopenharmony_ci        p[2 * i]     += (I_LFTG_DELTA * (p[2 * i - 1] + p[2 * i + 1]) + (1 << 15)) >> 16;
245cabdff1aSopenharmony_ci}
246cabdff1aSopenharmony_ci
247cabdff1aSopenharmony_cistatic void dwt_encode97_int(DWTContext *s, int *t)
248cabdff1aSopenharmony_ci{
249cabdff1aSopenharmony_ci    int lev;
250cabdff1aSopenharmony_ci    int w = s->linelen[s->ndeclevels-1][0];
251cabdff1aSopenharmony_ci    int h = s->linelen[s->ndeclevels-1][1];
252cabdff1aSopenharmony_ci    int i;
253cabdff1aSopenharmony_ci    int *line = s->i_linebuf;
254cabdff1aSopenharmony_ci    line += 5;
255cabdff1aSopenharmony_ci
256cabdff1aSopenharmony_ci    for (i = 0; i < w * h; i++)
257cabdff1aSopenharmony_ci        t[i] *= 1 << I_PRESHIFT;
258cabdff1aSopenharmony_ci
259cabdff1aSopenharmony_ci    for (lev = s->ndeclevels-1; lev >= 0; lev--){
260cabdff1aSopenharmony_ci        int lh = s->linelen[lev][0],
261cabdff1aSopenharmony_ci            lv = s->linelen[lev][1],
262cabdff1aSopenharmony_ci            mh = s->mod[lev][0],
263cabdff1aSopenharmony_ci            mv = s->mod[lev][1],
264cabdff1aSopenharmony_ci            lp;
265cabdff1aSopenharmony_ci        int *l;
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ci        // VER_SD
268cabdff1aSopenharmony_ci        l = line + mv;
269cabdff1aSopenharmony_ci        for (lp = 0; lp < lh; lp++) {
270cabdff1aSopenharmony_ci            int i, j = 0;
271cabdff1aSopenharmony_ci
272cabdff1aSopenharmony_ci            for (i = 0; i < lv; i++)
273cabdff1aSopenharmony_ci                l[i] = t[w*i + lp];
274cabdff1aSopenharmony_ci
275cabdff1aSopenharmony_ci            sd_1d97_int(line, mv, mv + lv);
276cabdff1aSopenharmony_ci
277cabdff1aSopenharmony_ci            // copy back and deinterleave
278cabdff1aSopenharmony_ci            for (i =   mv; i < lv; i+=2, j++)
279cabdff1aSopenharmony_ci                t[w*j + lp] = ((l[i] * I_LFTG_X) + (1 << 15)) >> 16;
280cabdff1aSopenharmony_ci            for (i = 1-mv; i < lv; i+=2, j++)
281cabdff1aSopenharmony_ci                t[w*j + lp] = l[i];
282cabdff1aSopenharmony_ci        }
283cabdff1aSopenharmony_ci
284cabdff1aSopenharmony_ci        // HOR_SD
285cabdff1aSopenharmony_ci        l = line + mh;
286cabdff1aSopenharmony_ci        for (lp = 0; lp < lv; lp++){
287cabdff1aSopenharmony_ci            int i, j = 0;
288cabdff1aSopenharmony_ci
289cabdff1aSopenharmony_ci            for (i = 0; i < lh; i++)
290cabdff1aSopenharmony_ci                l[i] = t[w*lp + i];
291cabdff1aSopenharmony_ci
292cabdff1aSopenharmony_ci            sd_1d97_int(line, mh, mh + lh);
293cabdff1aSopenharmony_ci
294cabdff1aSopenharmony_ci            // copy back and deinterleave
295cabdff1aSopenharmony_ci            for (i =   mh; i < lh; i+=2, j++)
296cabdff1aSopenharmony_ci                t[w*lp + j] = ((l[i] * I_LFTG_X) + (1 << 15)) >> 16;
297cabdff1aSopenharmony_ci            for (i = 1-mh; i < lh; i+=2, j++)
298cabdff1aSopenharmony_ci                t[w*lp + j] = l[i];
299cabdff1aSopenharmony_ci        }
300cabdff1aSopenharmony_ci
301cabdff1aSopenharmony_ci    }
302cabdff1aSopenharmony_ci
303cabdff1aSopenharmony_ci    for (i = 0; i < w * h; i++)
304cabdff1aSopenharmony_ci        t[i] = (t[i] + ((1<<I_PRESHIFT)>>1)) >> I_PRESHIFT;
305cabdff1aSopenharmony_ci}
306cabdff1aSopenharmony_ci
307cabdff1aSopenharmony_cistatic void sr_1d53(unsigned *p, int i0, int i1)
308cabdff1aSopenharmony_ci{
309cabdff1aSopenharmony_ci    int i;
310cabdff1aSopenharmony_ci
311cabdff1aSopenharmony_ci    if (i1 <= i0 + 1) {
312cabdff1aSopenharmony_ci        if (i0 == 1)
313cabdff1aSopenharmony_ci            p[1] = (int)p[1] >> 1;
314cabdff1aSopenharmony_ci        return;
315cabdff1aSopenharmony_ci    }
316cabdff1aSopenharmony_ci
317cabdff1aSopenharmony_ci    extend53(p, i0, i1);
318cabdff1aSopenharmony_ci
319cabdff1aSopenharmony_ci    for (i = (i0 >> 1); i < (i1 >> 1) + 1; i++)
320cabdff1aSopenharmony_ci        p[2 * i] -= (int)(p[2 * i - 1] + p[2 * i + 1] + 2) >> 2;
321cabdff1aSopenharmony_ci    for (i = (i0 >> 1); i < (i1 >> 1); i++)
322cabdff1aSopenharmony_ci        p[2 * i + 1] += (int)(p[2 * i] + p[2 * i + 2]) >> 1;
323cabdff1aSopenharmony_ci}
324cabdff1aSopenharmony_ci
325cabdff1aSopenharmony_cistatic void dwt_decode53(DWTContext *s, int *t)
326cabdff1aSopenharmony_ci{
327cabdff1aSopenharmony_ci    int lev;
328cabdff1aSopenharmony_ci    int w     = s->linelen[s->ndeclevels - 1][0];
329cabdff1aSopenharmony_ci    int32_t *line = s->i_linebuf;
330cabdff1aSopenharmony_ci    line += 3;
331cabdff1aSopenharmony_ci
332cabdff1aSopenharmony_ci    for (lev = 0; lev < s->ndeclevels; lev++) {
333cabdff1aSopenharmony_ci        int lh = s->linelen[lev][0],
334cabdff1aSopenharmony_ci            lv = s->linelen[lev][1],
335cabdff1aSopenharmony_ci            mh = s->mod[lev][0],
336cabdff1aSopenharmony_ci            mv = s->mod[lev][1],
337cabdff1aSopenharmony_ci            lp;
338cabdff1aSopenharmony_ci        int *l;
339cabdff1aSopenharmony_ci
340cabdff1aSopenharmony_ci        // HOR_SD
341cabdff1aSopenharmony_ci        l = line + mh;
342cabdff1aSopenharmony_ci        for (lp = 0; lp < lv; lp++) {
343cabdff1aSopenharmony_ci            int i, j = 0;
344cabdff1aSopenharmony_ci            // copy with interleaving
345cabdff1aSopenharmony_ci            for (i = mh; i < lh; i += 2, j++)
346cabdff1aSopenharmony_ci                l[i] = t[w * lp + j];
347cabdff1aSopenharmony_ci            for (i = 1 - mh; i < lh; i += 2, j++)
348cabdff1aSopenharmony_ci                l[i] = t[w * lp + j];
349cabdff1aSopenharmony_ci
350cabdff1aSopenharmony_ci            sr_1d53(line, mh, mh + lh);
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ci            for (i = 0; i < lh; i++)
353cabdff1aSopenharmony_ci                t[w * lp + i] = l[i];
354cabdff1aSopenharmony_ci        }
355cabdff1aSopenharmony_ci
356cabdff1aSopenharmony_ci        // VER_SD
357cabdff1aSopenharmony_ci        l = line + mv;
358cabdff1aSopenharmony_ci        for (lp = 0; lp < lh; lp++) {
359cabdff1aSopenharmony_ci            int i, j = 0;
360cabdff1aSopenharmony_ci            // copy with interleaving
361cabdff1aSopenharmony_ci            for (i = mv; i < lv; i += 2, j++)
362cabdff1aSopenharmony_ci                l[i] = t[w * j + lp];
363cabdff1aSopenharmony_ci            for (i = 1 - mv; i < lv; i += 2, j++)
364cabdff1aSopenharmony_ci                l[i] = t[w * j + lp];
365cabdff1aSopenharmony_ci
366cabdff1aSopenharmony_ci            sr_1d53(line, mv, mv + lv);
367cabdff1aSopenharmony_ci
368cabdff1aSopenharmony_ci            for (i = 0; i < lv; i++)
369cabdff1aSopenharmony_ci                t[w * i + lp] = l[i];
370cabdff1aSopenharmony_ci        }
371cabdff1aSopenharmony_ci    }
372cabdff1aSopenharmony_ci}
373cabdff1aSopenharmony_ci
374cabdff1aSopenharmony_cistatic void sr_1d97_float(float *p, int i0, int i1)
375cabdff1aSopenharmony_ci{
376cabdff1aSopenharmony_ci    int i;
377cabdff1aSopenharmony_ci
378cabdff1aSopenharmony_ci    if (i1 <= i0 + 1) {
379cabdff1aSopenharmony_ci        if (i0 == 1)
380cabdff1aSopenharmony_ci            p[1] *= F_LFTG_K/2;
381cabdff1aSopenharmony_ci        else
382cabdff1aSopenharmony_ci            p[0] *= F_LFTG_X;
383cabdff1aSopenharmony_ci        return;
384cabdff1aSopenharmony_ci    }
385cabdff1aSopenharmony_ci
386cabdff1aSopenharmony_ci    extend97_float(p, i0, i1);
387cabdff1aSopenharmony_ci
388cabdff1aSopenharmony_ci    for (i = (i0 >> 1) - 1; i < (i1 >> 1) + 2; i++)
389cabdff1aSopenharmony_ci        p[2 * i]     -= F_LFTG_DELTA * (p[2 * i - 1] + p[2 * i + 1]);
390cabdff1aSopenharmony_ci    /* step 4 */
391cabdff1aSopenharmony_ci    for (i = (i0 >> 1) - 1; i < (i1 >> 1) + 1; i++)
392cabdff1aSopenharmony_ci        p[2 * i + 1] -= F_LFTG_GAMMA * (p[2 * i]     + p[2 * i + 2]);
393cabdff1aSopenharmony_ci    /*step 5*/
394cabdff1aSopenharmony_ci    for (i = (i0 >> 1); i < (i1 >> 1) + 1; i++)
395cabdff1aSopenharmony_ci        p[2 * i]     += F_LFTG_BETA  * (p[2 * i - 1] + p[2 * i + 1]);
396cabdff1aSopenharmony_ci    /* step 6 */
397cabdff1aSopenharmony_ci    for (i = (i0 >> 1); i < (i1 >> 1); i++)
398cabdff1aSopenharmony_ci        p[2 * i + 1] += F_LFTG_ALPHA * (p[2 * i]     + p[2 * i + 2]);
399cabdff1aSopenharmony_ci}
400cabdff1aSopenharmony_ci
401cabdff1aSopenharmony_cistatic void dwt_decode97_float(DWTContext *s, float *t)
402cabdff1aSopenharmony_ci{
403cabdff1aSopenharmony_ci    int lev;
404cabdff1aSopenharmony_ci    int w       = s->linelen[s->ndeclevels - 1][0];
405cabdff1aSopenharmony_ci    float *line = s->f_linebuf;
406cabdff1aSopenharmony_ci    float *data = t;
407cabdff1aSopenharmony_ci    /* position at index O of line range [0-5,w+5] cf. extend function */
408cabdff1aSopenharmony_ci    line += 5;
409cabdff1aSopenharmony_ci
410cabdff1aSopenharmony_ci    for (lev = 0; lev < s->ndeclevels; lev++) {
411cabdff1aSopenharmony_ci        int lh = s->linelen[lev][0],
412cabdff1aSopenharmony_ci            lv = s->linelen[lev][1],
413cabdff1aSopenharmony_ci            mh = s->mod[lev][0],
414cabdff1aSopenharmony_ci            mv = s->mod[lev][1],
415cabdff1aSopenharmony_ci            lp;
416cabdff1aSopenharmony_ci        float *l;
417cabdff1aSopenharmony_ci        // HOR_SD
418cabdff1aSopenharmony_ci        l = line + mh;
419cabdff1aSopenharmony_ci        for (lp = 0; lp < lv; lp++) {
420cabdff1aSopenharmony_ci            int i, j = 0;
421cabdff1aSopenharmony_ci            // copy with interleaving
422cabdff1aSopenharmony_ci            for (i = mh; i < lh; i += 2, j++)
423cabdff1aSopenharmony_ci                l[i] = data[w * lp + j];
424cabdff1aSopenharmony_ci            for (i = 1 - mh; i < lh; i += 2, j++)
425cabdff1aSopenharmony_ci                l[i] = data[w * lp + j];
426cabdff1aSopenharmony_ci
427cabdff1aSopenharmony_ci            sr_1d97_float(line, mh, mh + lh);
428cabdff1aSopenharmony_ci
429cabdff1aSopenharmony_ci            for (i = 0; i < lh; i++)
430cabdff1aSopenharmony_ci                data[w * lp + i] = l[i];
431cabdff1aSopenharmony_ci        }
432cabdff1aSopenharmony_ci
433cabdff1aSopenharmony_ci        // VER_SD
434cabdff1aSopenharmony_ci        l = line + mv;
435cabdff1aSopenharmony_ci        for (lp = 0; lp < lh; lp++) {
436cabdff1aSopenharmony_ci            int i, j = 0;
437cabdff1aSopenharmony_ci            // copy with interleaving
438cabdff1aSopenharmony_ci            for (i = mv; i < lv; i += 2, j++)
439cabdff1aSopenharmony_ci                l[i] = data[w * j + lp];
440cabdff1aSopenharmony_ci            for (i = 1 - mv; i < lv; i += 2, j++)
441cabdff1aSopenharmony_ci                l[i] = data[w * j + lp];
442cabdff1aSopenharmony_ci
443cabdff1aSopenharmony_ci            sr_1d97_float(line, mv, mv + lv);
444cabdff1aSopenharmony_ci
445cabdff1aSopenharmony_ci            for (i = 0; i < lv; i++)
446cabdff1aSopenharmony_ci                data[w * i + lp] = l[i];
447cabdff1aSopenharmony_ci        }
448cabdff1aSopenharmony_ci    }
449cabdff1aSopenharmony_ci}
450cabdff1aSopenharmony_ci
451cabdff1aSopenharmony_cistatic void sr_1d97_int(int32_t *p, int i0, int i1)
452cabdff1aSopenharmony_ci{
453cabdff1aSopenharmony_ci    int i;
454cabdff1aSopenharmony_ci
455cabdff1aSopenharmony_ci    if (i1 <= i0 + 1) {
456cabdff1aSopenharmony_ci        if (i0 == 1)
457cabdff1aSopenharmony_ci            p[1] = (p[1] * I_LFTG_K + (1<<16)) >> 17;
458cabdff1aSopenharmony_ci        else
459cabdff1aSopenharmony_ci            p[0] = (p[0] * I_LFTG_X + (1<<15)) >> 16;
460cabdff1aSopenharmony_ci        return;
461cabdff1aSopenharmony_ci    }
462cabdff1aSopenharmony_ci
463cabdff1aSopenharmony_ci    extend97_int(p, i0, i1);
464cabdff1aSopenharmony_ci
465cabdff1aSopenharmony_ci    for (i = (i0 >> 1) - 1; i < (i1 >> 1) + 2; i++)
466cabdff1aSopenharmony_ci        p[2 * i]     -= (I_LFTG_DELTA * (p[2 * i - 1] + (int64_t)p[2 * i + 1]) + (1 << 15)) >> 16;
467cabdff1aSopenharmony_ci    /* step 4 */
468cabdff1aSopenharmony_ci    for (i = (i0 >> 1) - 1; i < (i1 >> 1) + 1; i++)
469cabdff1aSopenharmony_ci        p[2 * i + 1] -= (I_LFTG_GAMMA * (p[2 * i]     + (int64_t)p[2 * i + 2]) + (1 << 15)) >> 16;
470cabdff1aSopenharmony_ci    /*step 5*/
471cabdff1aSopenharmony_ci    for (i = (i0 >> 1); i < (i1 >> 1) + 1; i++)
472cabdff1aSopenharmony_ci        p[2 * i]     += (I_LFTG_BETA  * (p[2 * i - 1] + (int64_t)p[2 * i + 1]) + (1 << 15)) >> 16;
473cabdff1aSopenharmony_ci    /* step 6 */
474cabdff1aSopenharmony_ci    for (i = (i0 >> 1); i < (i1 >> 1); i++)
475cabdff1aSopenharmony_ci        p[2 * i + 1] += (I_LFTG_ALPHA * (p[2 * i]     + (int64_t)p[2 * i + 2]) + (1 << 15)) >> 16;
476cabdff1aSopenharmony_ci}
477cabdff1aSopenharmony_ci
478cabdff1aSopenharmony_cistatic void dwt_decode97_int(DWTContext *s, int32_t *t)
479cabdff1aSopenharmony_ci{
480cabdff1aSopenharmony_ci    int lev;
481cabdff1aSopenharmony_ci    int w       = s->linelen[s->ndeclevels - 1][0];
482cabdff1aSopenharmony_ci    int h       = s->linelen[s->ndeclevels - 1][1];
483cabdff1aSopenharmony_ci    int i;
484cabdff1aSopenharmony_ci    int32_t *line = s->i_linebuf;
485cabdff1aSopenharmony_ci    int32_t *data = t;
486cabdff1aSopenharmony_ci    /* position at index O of line range [0-5,w+5] cf. extend function */
487cabdff1aSopenharmony_ci    line += 5;
488cabdff1aSopenharmony_ci
489cabdff1aSopenharmony_ci    for (i = 0; i < w * h; i++)
490cabdff1aSopenharmony_ci        data[i] *= 1LL << I_PRESHIFT;
491cabdff1aSopenharmony_ci
492cabdff1aSopenharmony_ci    for (lev = 0; lev < s->ndeclevels; lev++) {
493cabdff1aSopenharmony_ci        int lh = s->linelen[lev][0],
494cabdff1aSopenharmony_ci            lv = s->linelen[lev][1],
495cabdff1aSopenharmony_ci            mh = s->mod[lev][0],
496cabdff1aSopenharmony_ci            mv = s->mod[lev][1],
497cabdff1aSopenharmony_ci            lp;
498cabdff1aSopenharmony_ci        int32_t *l;
499cabdff1aSopenharmony_ci        // HOR_SD
500cabdff1aSopenharmony_ci        l = line + mh;
501cabdff1aSopenharmony_ci        for (lp = 0; lp < lv; lp++) {
502cabdff1aSopenharmony_ci            int i, j = 0;
503cabdff1aSopenharmony_ci            // rescale with interleaving
504cabdff1aSopenharmony_ci            for (i = mh; i < lh; i += 2, j++)
505cabdff1aSopenharmony_ci                l[i] = ((data[w * lp + j] * I_LFTG_K) + (1 << 15)) >> 16;
506cabdff1aSopenharmony_ci            for (i = 1 - mh; i < lh; i += 2, j++)
507cabdff1aSopenharmony_ci                l[i] = data[w * lp + j];
508cabdff1aSopenharmony_ci
509cabdff1aSopenharmony_ci            sr_1d97_int(line, mh, mh + lh);
510cabdff1aSopenharmony_ci
511cabdff1aSopenharmony_ci            for (i = 0; i < lh; i++)
512cabdff1aSopenharmony_ci                data[w * lp + i] = l[i];
513cabdff1aSopenharmony_ci        }
514cabdff1aSopenharmony_ci
515cabdff1aSopenharmony_ci        // VER_SD
516cabdff1aSopenharmony_ci        l = line + mv;
517cabdff1aSopenharmony_ci        for (lp = 0; lp < lh; lp++) {
518cabdff1aSopenharmony_ci            int i, j = 0;
519cabdff1aSopenharmony_ci            // rescale with interleaving
520cabdff1aSopenharmony_ci            for (i = mv; i < lv; i += 2, j++)
521cabdff1aSopenharmony_ci                l[i] = ((data[w * j + lp] * I_LFTG_K) + (1 << 15)) >> 16;
522cabdff1aSopenharmony_ci            for (i = 1 - mv; i < lv; i += 2, j++)
523cabdff1aSopenharmony_ci                l[i] = data[w * j + lp];
524cabdff1aSopenharmony_ci
525cabdff1aSopenharmony_ci            sr_1d97_int(line, mv, mv + lv);
526cabdff1aSopenharmony_ci
527cabdff1aSopenharmony_ci            for (i = 0; i < lv; i++)
528cabdff1aSopenharmony_ci                data[w * i + lp] = l[i];
529cabdff1aSopenharmony_ci        }
530cabdff1aSopenharmony_ci    }
531cabdff1aSopenharmony_ci
532cabdff1aSopenharmony_ci    for (i = 0; i < w * h; i++)
533cabdff1aSopenharmony_ci        data[i] = (data[i] + ((1LL<<I_PRESHIFT)>>1)) >> I_PRESHIFT;
534cabdff1aSopenharmony_ci}
535cabdff1aSopenharmony_ci
536cabdff1aSopenharmony_ciint ff_jpeg2000_dwt_init(DWTContext *s, int border[2][2],
537cabdff1aSopenharmony_ci                         int decomp_levels, int type)
538cabdff1aSopenharmony_ci{
539cabdff1aSopenharmony_ci    int i, j, lev = decomp_levels, maxlen,
540cabdff1aSopenharmony_ci        b[2][2];
541cabdff1aSopenharmony_ci
542cabdff1aSopenharmony_ci    s->ndeclevels = decomp_levels;
543cabdff1aSopenharmony_ci    s->type       = type;
544cabdff1aSopenharmony_ci
545cabdff1aSopenharmony_ci    for (i = 0; i < 2; i++)
546cabdff1aSopenharmony_ci        for (j = 0; j < 2; j++)
547cabdff1aSopenharmony_ci            b[i][j] = border[i][j];
548cabdff1aSopenharmony_ci
549cabdff1aSopenharmony_ci    maxlen = FFMAX(b[0][1] - b[0][0],
550cabdff1aSopenharmony_ci                   b[1][1] - b[1][0]);
551cabdff1aSopenharmony_ci    while (--lev >= 0)
552cabdff1aSopenharmony_ci        for (i = 0; i < 2; i++) {
553cabdff1aSopenharmony_ci            s->linelen[lev][i] = b[i][1] - b[i][0];
554cabdff1aSopenharmony_ci            s->mod[lev][i]     = b[i][0] & 1;
555cabdff1aSopenharmony_ci            for (j = 0; j < 2; j++)
556cabdff1aSopenharmony_ci                b[i][j] = (b[i][j] + 1) >> 1;
557cabdff1aSopenharmony_ci        }
558cabdff1aSopenharmony_ci    switch (type) {
559cabdff1aSopenharmony_ci    case FF_DWT97:
560cabdff1aSopenharmony_ci        s->f_linebuf = av_malloc_array((maxlen + 12), sizeof(*s->f_linebuf));
561cabdff1aSopenharmony_ci        if (!s->f_linebuf)
562cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
563cabdff1aSopenharmony_ci        break;
564cabdff1aSopenharmony_ci     case FF_DWT97_INT:
565cabdff1aSopenharmony_ci        s->i_linebuf = av_malloc_array((maxlen + 12), sizeof(*s->i_linebuf));
566cabdff1aSopenharmony_ci        if (!s->i_linebuf)
567cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
568cabdff1aSopenharmony_ci        break;
569cabdff1aSopenharmony_ci    case FF_DWT53:
570cabdff1aSopenharmony_ci        s->i_linebuf = av_malloc_array((maxlen +  6), sizeof(*s->i_linebuf));
571cabdff1aSopenharmony_ci        if (!s->i_linebuf)
572cabdff1aSopenharmony_ci            return AVERROR(ENOMEM);
573cabdff1aSopenharmony_ci        break;
574cabdff1aSopenharmony_ci    default:
575cabdff1aSopenharmony_ci        return -1;
576cabdff1aSopenharmony_ci    }
577cabdff1aSopenharmony_ci    return 0;
578cabdff1aSopenharmony_ci}
579cabdff1aSopenharmony_ci
580cabdff1aSopenharmony_ciint ff_dwt_encode(DWTContext *s, void *t)
581cabdff1aSopenharmony_ci{
582cabdff1aSopenharmony_ci    if (s->ndeclevels == 0)
583cabdff1aSopenharmony_ci        return 0;
584cabdff1aSopenharmony_ci
585cabdff1aSopenharmony_ci    switch(s->type){
586cabdff1aSopenharmony_ci        case FF_DWT97:
587cabdff1aSopenharmony_ci            dwt_encode97_float(s, t); break;
588cabdff1aSopenharmony_ci        case FF_DWT97_INT:
589cabdff1aSopenharmony_ci            dwt_encode97_int(s, t); break;
590cabdff1aSopenharmony_ci        case FF_DWT53:
591cabdff1aSopenharmony_ci            dwt_encode53(s, t); break;
592cabdff1aSopenharmony_ci        default:
593cabdff1aSopenharmony_ci            return -1;
594cabdff1aSopenharmony_ci    }
595cabdff1aSopenharmony_ci    return 0;
596cabdff1aSopenharmony_ci}
597cabdff1aSopenharmony_ci
598cabdff1aSopenharmony_ciint ff_dwt_decode(DWTContext *s, void *t)
599cabdff1aSopenharmony_ci{
600cabdff1aSopenharmony_ci    if (s->ndeclevels == 0)
601cabdff1aSopenharmony_ci        return 0;
602cabdff1aSopenharmony_ci
603cabdff1aSopenharmony_ci    switch (s->type) {
604cabdff1aSopenharmony_ci    case FF_DWT97:
605cabdff1aSopenharmony_ci        dwt_decode97_float(s, t);
606cabdff1aSopenharmony_ci        break;
607cabdff1aSopenharmony_ci    case FF_DWT97_INT:
608cabdff1aSopenharmony_ci        dwt_decode97_int(s, t);
609cabdff1aSopenharmony_ci        break;
610cabdff1aSopenharmony_ci    case FF_DWT53:
611cabdff1aSopenharmony_ci        dwt_decode53(s, t);
612cabdff1aSopenharmony_ci        break;
613cabdff1aSopenharmony_ci    default:
614cabdff1aSopenharmony_ci        return -1;
615cabdff1aSopenharmony_ci    }
616cabdff1aSopenharmony_ci    return 0;
617cabdff1aSopenharmony_ci}
618cabdff1aSopenharmony_ci
619cabdff1aSopenharmony_civoid ff_dwt_destroy(DWTContext *s)
620cabdff1aSopenharmony_ci{
621cabdff1aSopenharmony_ci    av_freep(&s->f_linebuf);
622cabdff1aSopenharmony_ci    av_freep(&s->i_linebuf);
623cabdff1aSopenharmony_ci}
624