1/*
2 * Discrete wavelet transform
3 * Copyright (c) 2007 Kamil Nowosad
4 * Copyright (c) 2013 Nicolas Bertrand <nicoinattendu@gmail.com>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <inttypes.h>
24#include <stdio.h>
25
26#include "libavutil/common.h"
27
28#include "libavcodec/jpeg2000dwt.c"
29
30#include "libavutil/lfg.h"
31
32#define MAX_W 256
33
34static int test_dwt(int *array, int *ref, int border[2][2], int decomp_levels, int type, int max_diff) {
35    int ret, j;
36    DWTContext s1={{{0}}}, *s= &s1;
37    int64_t err2 = 0;
38
39    ret = ff_jpeg2000_dwt_init(s,  border, decomp_levels, type);
40    if (ret < 0) {
41        fprintf(stderr, "ff_jpeg2000_dwt_init failed\n");
42        return 1;
43    }
44    ret = ff_dwt_encode(s, array);
45    if (ret < 0) {
46        fprintf(stderr, "ff_dwt_encode failed\n");
47        return 1;
48    }
49    ret = ff_dwt_decode(s, array);
50    if (ret < 0) {
51        fprintf(stderr, "ff_dwt_encode failed\n");
52        return 1;
53    }
54    for (j = 0; j<MAX_W * MAX_W; j++) {
55        if (FFABS(array[j] - ref[j]) > max_diff) {
56            fprintf(stderr, "missmatch at %d (%d != %d) decomp:%d border %d %d %d %d\n",
57                    j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]);
58            return 2;
59        }
60        err2 += (array[j] - ref[j]) * (array[j] - ref[j]);
61        array[j] = ref[j];
62    }
63    ff_dwt_destroy(s);
64
65    printf("%s, decomp:%2d border %3d %3d %3d %3d milli-err2:%9"PRId64"\n",
66           type == FF_DWT53 ? "5/3i" : "9/7i",
67           decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1],
68           1000*err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0])));
69
70    return 0;
71}
72
73static int test_dwtf(float *array, float *ref, int border[2][2], int decomp_levels, float max_diff) {
74    int ret, j;
75    DWTContext s1={{{0}}}, *s= &s1;
76    double err2 = 0;
77
78    ret = ff_jpeg2000_dwt_init(s,  border, decomp_levels, FF_DWT97);
79    if (ret < 0) {
80        fprintf(stderr, "ff_jpeg2000_dwt_init failed\n");
81        return 1;
82    }
83    ret = ff_dwt_encode(s, array);
84    if (ret < 0) {
85        fprintf(stderr, "ff_dwt_encode failed\n");
86        return 1;
87    }
88    ret = ff_dwt_decode(s, array);
89    if (ret < 0) {
90        fprintf(stderr, "ff_dwt_encode failed\n");
91        return 1;
92    }
93    for (j = 0; j<MAX_W * MAX_W; j++) {
94        if (FFABS(array[j] - ref[j]) > max_diff) {
95            fprintf(stderr, "missmatch at %d (%f != %f) decomp:%d border %d %d %d %d\n",
96                    j, array[j], ref[j],decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1]);
97            return 2;
98        }
99        err2 += (array[j] - ref[j]) * (array[j] - ref[j]);
100        array[j] = ref[j];
101    }
102    ff_dwt_destroy(s);
103
104    printf("9/7f, decomp:%2d border %3d %3d %3d %3d err2:%20.3f\n",
105           decomp_levels, border[0][0], border[0][1], border[1][0], border[1][1],
106           err2 / ((border[0][1] - border[0][0])*(border[1][1] - border[1][0])));
107
108    return 0;
109}
110
111static int array[MAX_W * MAX_W];
112static int ref  [MAX_W * MAX_W];
113static float arrayf[MAX_W * MAX_W];
114static float reff  [MAX_W * MAX_W];
115
116int main(void) {
117    AVLFG prng;
118    int i,j;
119    int border[2][2];
120    int ret, decomp_levels;
121
122    av_lfg_init(&prng, 1);
123
124    for (i = 0; i<MAX_W * MAX_W; i++)
125        arrayf[i] = reff[i] = array[i] = ref[i] =  av_lfg_get(&prng) % 2048;
126
127    for (i = 0; i < 100; i++) {
128        for (j=0; j<4; j++)
129            border[j>>1][j&1] = av_lfg_get(&prng) % MAX_W;
130        if (border[0][0] >= border[0][1] || border[1][0] >= border[1][1])
131            continue;
132        decomp_levels = av_lfg_get(&prng) % FF_DWT_MAX_DECLVLS;
133
134        ret = test_dwt(array, ref, border, decomp_levels, FF_DWT53, 0);
135        if (ret)
136            return ret;
137        ret = test_dwt(array, ref, border, decomp_levels, FF_DWT97_INT, FFMIN(7+5*decomp_levels, 15+3*decomp_levels));
138        if (ret)
139            return ret;
140        ret = test_dwtf(arrayf, reff, border, decomp_levels, 0.05);
141        if (ret)
142            return ret;
143    }
144
145    return 0;
146}
147