Merge pull request #954 from jeroen/static
[openjpeg.git] / src / lib / openjp2 / bench_dwt.c
1 /*
2  * The copyright in this software is being made available under the 2-clauses
3  * BSD License, included below. This software may be subject to other third
4  * party and contributor rights, including patent rights, and no such rights
5  * are granted under this license.
6  *
7  * Copyright (c) 2017, IntoPix SA <contact@intopix.com>
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "opj_includes.h"
33
34 #ifdef _WIN32
35 #include <windows.h>
36 #else
37 #include <sys/time.h>
38 #include <sys/resource.h>
39 #include <sys/times.h>
40 #endif /* _WIN32 */
41
42 OPJ_INT32 getValue(OPJ_UINT32 i)
43 {
44     return ((OPJ_INT32)i % 511) - 256;
45 }
46
47 void init_tilec(opj_tcd_tilecomp_t * l_tilec,
48                 OPJ_INT32 x0,
49                 OPJ_INT32 y0,
50                 OPJ_INT32 x1,
51                 OPJ_INT32 y1,
52                 OPJ_UINT32 numresolutions)
53 {
54     opj_tcd_resolution_t* l_res;
55     OPJ_UINT32 resno, l_level_no;
56     size_t i, nValues;
57
58     memset(l_tilec, 0, sizeof(*l_tilec));
59     l_tilec->x0 = x0;
60     l_tilec->y0 = y0;
61     l_tilec->x1 = x1;
62     l_tilec->y1 = y1;
63     nValues = (size_t)(l_tilec->x1 - l_tilec->x0) *
64               (size_t)(l_tilec->y1 - l_tilec->y0);
65     l_tilec->data = opj_malloc(sizeof(OPJ_INT32) * nValues);
66     for (i = 0; i < nValues; i++) {
67         l_tilec->data[i] = getValue(i);
68     }
69     l_tilec->numresolutions = numresolutions;
70     l_tilec->resolutions = opj_calloc(l_tilec->numresolutions,
71                                       sizeof(opj_tcd_resolution_t));
72
73     l_level_no = l_tilec->numresolutions;
74     l_res = l_tilec->resolutions;
75
76     /* Adapted from opj_tcd_init_tile() */
77     for (resno = 0; resno < l_tilec->numresolutions; ++resno) {
78
79         --l_level_no;
80
81         /* border for each resolution level (global) */
82         l_res->x0 = opj_int_ceildivpow2(l_tilec->x0, (OPJ_INT32)l_level_no);
83         l_res->y0 = opj_int_ceildivpow2(l_tilec->y0, (OPJ_INT32)l_level_no);
84         l_res->x1 = opj_int_ceildivpow2(l_tilec->x1, (OPJ_INT32)l_level_no);
85         l_res->y1 = opj_int_ceildivpow2(l_tilec->y1, (OPJ_INT32)l_level_no);
86
87         ++l_res;
88     }
89 }
90
91 void free_tilec(opj_tcd_tilecomp_t * l_tilec)
92 {
93     opj_free(l_tilec->data);
94     opj_free(l_tilec->resolutions);
95 }
96
97 void usage(void)
98 {
99     printf(
100         "bench_dwt [-size value] [-check] [-display] [-num_resolutions val]\n");
101     printf(
102         "          [-offset x y] [-num_threads val]\n");
103     exit(1);
104 }
105
106
107 OPJ_FLOAT64 opj_clock(void)
108 {
109 #ifdef _WIN32
110     /* _WIN32: use QueryPerformance (very accurate) */
111     LARGE_INTEGER freq, t ;
112     /* freq is the clock speed of the CPU */
113     QueryPerformanceFrequency(&freq) ;
114     /* cout << "freq = " << ((double) freq.QuadPart) << endl; */
115     /* t is the high resolution performance counter (see MSDN) */
116     QueryPerformanceCounter(& t) ;
117     return freq.QuadPart ? (t.QuadPart / (OPJ_FLOAT64) freq.QuadPart) : 0 ;
118 #else
119     /* Unix or Linux: use resource usage */
120     struct rusage t;
121     OPJ_FLOAT64 procTime;
122     /* (1) Get the rusage data structure at this moment (man getrusage) */
123     getrusage(0, &t);
124     /* (2) What is the elapsed time ? - CPU time = User time + System time */
125     /* (2a) Get the seconds */
126     procTime = (OPJ_FLOAT64)(t.ru_utime.tv_sec + t.ru_stime.tv_sec);
127     /* (2b) More precisely! Get the microseconds part ! */
128     return (procTime + (OPJ_FLOAT64)(t.ru_utime.tv_usec + t.ru_stime.tv_usec) *
129             1e-6) ;
130 #endif
131 }
132
133 int main(int argc, char** argv)
134 {
135     int num_threads = 0;
136     opj_tcd_tilecomp_t tilec;
137     opj_thread_pool_t* tp;
138     OPJ_INT32 i, j, k;
139     OPJ_BOOL display = OPJ_FALSE;
140     OPJ_BOOL check = OPJ_FALSE;
141     OPJ_INT32 size = 16384 - 1;
142     OPJ_FLOAT64 start, stop;
143     OPJ_UINT32 offset_x = (size + 1) / 2 - 1;
144     OPJ_UINT32 offset_y = (size + 1) / 2 - 1;
145     OPJ_UINT32 num_resolutions = 6;
146
147     for (i = 1; i < argc; i++) {
148         if (strcmp(argv[i], "-display") == 0) {
149             display = OPJ_TRUE;
150             check = OPJ_TRUE;
151         } else if (strcmp(argv[i], "-check") == 0) {
152             check = OPJ_TRUE;
153         } else if (strcmp(argv[i], "-size") == 0 && i + 1 < argc) {
154             size = atoi(argv[i + 1]);
155             i ++;
156         } else if (strcmp(argv[i], "-num_threads") == 0 && i + 1 < argc) {
157             num_threads = atoi(argv[i + 1]);
158             i ++;
159         } else if (strcmp(argv[i], "-num_resolutions") == 0 && i + 1 < argc) {
160             num_resolutions = atoi(argv[i + 1]);
161             if (num_resolutions == 0 || num_resolutions > 32) {
162                 fprintf(stderr,
163                         "Invalid value for num_resolutions. Should be >= 1 and <= 32\n");
164                 exit(1);
165             }
166             i ++;
167         } else if (strcmp(argv[i], "-offset") == 0 && i + 2 < argc) {
168             offset_x = atoi(argv[i + 1]);
169             offset_y = atoi(argv[i + 2]);
170             i += 2;
171         } else {
172             usage();
173         }
174     }
175
176     tp = opj_thread_pool_create(num_threads);
177
178     init_tilec(&tilec, offset_x, offset_y, offset_x + size, offset_y + size,
179                num_resolutions);
180
181     if (display) {
182         printf("Before\n");
183         k = 0;
184         for (j = 0; j < tilec.y1 - tilec.y0; j++) {
185             for (i = 0; i < tilec.x1 - tilec.x0; i++) {
186                 printf("%d ", tilec.data[k]);
187                 k ++;
188             }
189             printf("\n");
190         }
191     }
192
193     start = opj_clock();
194     opj_dwt_decode(tp, &tilec, tilec.numresolutions);
195     stop = opj_clock();
196     printf("time for dwt_decode: %.03f s\n", stop - start);
197
198     if (display || check) {
199         if (display) {
200             printf("After IDWT\n");
201             k = 0;
202             for (j = 0; j < tilec.y1 - tilec.y0; j++) {
203                 for (i = 0; i < tilec.x1 - tilec.x0; i++) {
204                     printf("%d ", tilec.data[k]);
205                     k ++;
206                 }
207                 printf("\n");
208             }
209         }
210
211         opj_dwt_encode(&tilec);
212         if (display) {
213             printf("After FDWT\n");
214             k = 0;
215             for (j = 0; j < tilec.y1 - tilec.y0; j++) {
216                 for (i = 0; i < tilec.x1 - tilec.x0; i++) {
217                     printf("%d ", tilec.data[k]);
218                     k ++;
219                 }
220                 printf("\n");
221             }
222         }
223
224         if (check) {
225             size_t idx;
226             size_t nValues = (size_t)(tilec.x1 - tilec.x0) *
227                              (size_t)(tilec.y1 - tilec.y0);
228             for (idx = 0; i < nValues; i++) {
229                 if (tilec.data[idx] != getValue(idx)) {
230                     printf("Difference found at idx = %u\n", (OPJ_UINT32)idx);
231                     exit(1);
232                 }
233             }
234         }
235     }
236
237     free_tilec(&tilec);
238
239     opj_thread_pool_destroy(tp);
240     return 0;
241 }