Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * Copyright (c) 2013 Nicolas George
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public License
8
 * as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg 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
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
 
21
/* Optional external libraries; can be enabled using:
22
 * make VERSUS=crypto+gcrypt+tomcrypt tools/crypto_bench */
23
#define USE_crypto           0x01    /* OpenSSL's libcrypto */
24
#define USE_gcrypt           0x02    /* GnuTLS's libgcrypt */
25
#define USE_tomcrypt         0x04    /* LibTomCrypt */
26
 
27
#include 
28
#include 
29
 
30
#include "libavutil/avutil.h"
31
#include "libavutil/avstring.h"
32
#include "libavutil/crc.h"
33
#include "libavutil/intreadwrite.h"
34
#include "libavutil/timer.h"
35
 
36
#if HAVE_UNISTD_H
37
#include  /* for getopt */
38
#endif
39
#if !HAVE_GETOPT
40
#include "compat/getopt.c"
41
#endif
42
 
43
#define MAX_INPUT_SIZE 1048576
44
#define MAX_OUTPUT_SIZE 128
45
 
46
static const char *enabled_libs;
47
static const char *enabled_algos;
48
static unsigned specified_runs;
49
 
50
static const uint8_t *hardcoded_key = "FFmpeg is the best program ever.";
51
 
52
static void fatal_error(const char *tag)
53
{
54
    av_log(NULL, AV_LOG_ERROR, "Fatal error: %s\n", tag);
55
    exit(1);
56
}
57
 
58
struct hash_impl {
59
    const char *lib;
60
    const char *name;
61
    void (*run)(uint8_t *output, const uint8_t *input, unsigned size);
62
    const char *output;
63
};
64
 
65
/***************************************************************************
66
 * lavu: libavutil
67
 ***************************************************************************/
68
 
69
#include "libavutil/md5.h"
70
#include "libavutil/sha.h"
71
#include "libavutil/sha512.h"
72
#include "libavutil/ripemd.h"
73
#include "libavutil/aes.h"
74
 
75
#define IMPL_USE_lavu IMPL_USE
76
 
77
static void run_lavu_md5(uint8_t *output,
78
                         const uint8_t *input, unsigned size)
79
{
80
    av_md5_sum(output, input, size);
81
}
82
 
83
#define DEFINE_LAVU_MD(suffix, type, namespace, hsize)                       \
84
static void run_lavu_ ## suffix(uint8_t *output,                             \
85
                                const uint8_t *input, unsigned size)         \
86
{                                                                            \
87
    static struct type *h;                                                   \
88
    if (!h && !(h = av_ ## namespace ## _alloc()))                           \
89
        fatal_error("out of memory");                                        \
90
    av_ ## namespace ## _init(h, hsize);                                     \
91
    av_ ## namespace ## _update(h, input, size);                             \
92
    av_ ## namespace ## _final(h, output);                                   \
93
}
94
 
95
DEFINE_LAVU_MD(sha1,      AVSHA,    sha, 160);
96
DEFINE_LAVU_MD(sha256,    AVSHA,    sha, 256);
97
DEFINE_LAVU_MD(sha512,    AVSHA512, sha512, 512);
98
DEFINE_LAVU_MD(ripemd160, AVRIPEMD, ripemd, 160);
99
 
100
static void run_lavu_aes128(uint8_t *output,
101
                            const uint8_t *input, unsigned size)
102
{
103
    static struct AVAES *aes;
104
    if (!aes && !(aes = av_aes_alloc()))
105
        fatal_error("out of memory");
106
    av_aes_init(aes, hardcoded_key, 128, 0);
107
    av_aes_crypt(aes, output, input, size >> 4, NULL, 0);
108
}
109
 
110
/***************************************************************************
111
 * crypto: OpenSSL's libcrypto
112
 ***************************************************************************/
113
 
114
#if (USE_EXT_LIBS) & USE_crypto
115
 
116
#include 
117
#include 
118
#include 
119
#include 
120
 
121
#define DEFINE_CRYPTO_WRAPPER(suffix, function)                              \
122
static void run_crypto_ ## suffix(uint8_t *output,                           \
123
                                  const uint8_t *input, unsigned size)       \
124
{                                                                            \
125
    function(input, size, output);                                           \
126
}
127
 
128
DEFINE_CRYPTO_WRAPPER(md5,       MD5)
129
DEFINE_CRYPTO_WRAPPER(sha1,      SHA1)
130
DEFINE_CRYPTO_WRAPPER(sha256,    SHA256)
131
DEFINE_CRYPTO_WRAPPER(sha512,    SHA512)
132
DEFINE_CRYPTO_WRAPPER(ripemd160, RIPEMD160)
133
 
134
static void run_crypto_aes128(uint8_t *output,
135
                              const uint8_t *input, unsigned size)
136
{
137
    AES_KEY aes;
138
    unsigned i;
139
 
140
    AES_set_encrypt_key(hardcoded_key, 128, &aes);
141
    size -= 15;
142
    for (i = 0; i < size; i += 16)
143
        AES_encrypt(input + i, output + i, &aes);
144
}
145
 
146
#define IMPL_USE_crypto(...) IMPL_USE(__VA_ARGS__)
147
#else
148
#define IMPL_USE_crypto(...) /* ignore */
149
#endif
150
 
151
/***************************************************************************
152
 * gcrypt: GnuTLS's libgcrypt
153
 ***************************************************************************/
154
 
155
#if (USE_EXT_LIBS) & USE_gcrypt
156
 
157
#include 
158
 
159
#define DEFINE_GCRYPT_WRAPPER(suffix, algo)                                  \
160
static void run_gcrypt_ ## suffix(uint8_t *output,                           \
161
                                  const uint8_t *input, unsigned size)       \
162
{                                                                            \
163
    gcry_md_hash_buffer(GCRY_MD_ ## algo, output, input, size);              \
164
}
165
 
166
DEFINE_GCRYPT_WRAPPER(md5,       MD5)
167
DEFINE_GCRYPT_WRAPPER(sha1,      SHA1)
168
DEFINE_GCRYPT_WRAPPER(sha256,    SHA256)
169
DEFINE_GCRYPT_WRAPPER(sha512,    SHA512)
170
DEFINE_GCRYPT_WRAPPER(ripemd160, RMD160)
171
 
172
static void run_gcrypt_aes128(uint8_t *output,
173
                              const uint8_t *input, unsigned size)
174
{
175
    static gcry_cipher_hd_t aes;
176
    if (aes == NULL)
177
        gcry_cipher_open(&aes, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_ECB, 0);
178
    gcry_cipher_setkey(aes, hardcoded_key, 16);
179
    gcry_cipher_encrypt(aes, output, size, input, size);
180
}
181
 
182
#define IMPL_USE_gcrypt(...) IMPL_USE(__VA_ARGS__)
183
#else
184
#define IMPL_USE_gcrypt(...) /* ignore */
185
#endif
186
 
187
/***************************************************************************
188
 * tomcrypt: LibTomCrypt
189
 ***************************************************************************/
190
 
191
#if (USE_EXT_LIBS) & USE_tomcrypt
192
 
193
#include 
194
 
195
#define DEFINE_TOMCRYPT_WRAPPER(suffix, namespace, algo)                     \
196
static void run_tomcrypt_ ## suffix(uint8_t *output,                         \
197
                                    const uint8_t *input, unsigned size)     \
198
{                                                                            \
199
    hash_state md;                                                           \
200
    namespace ## _init(&md);                                                 \
201
    namespace ## _process(&md, input, size);                                 \
202
    namespace ## _done(&md, output);                                         \
203
}
204
 
205
DEFINE_TOMCRYPT_WRAPPER(md5,       md5,    MD5)
206
DEFINE_TOMCRYPT_WRAPPER(sha1,      sha1,   SHA1)
207
DEFINE_TOMCRYPT_WRAPPER(sha256,    sha256, SHA256)
208
DEFINE_TOMCRYPT_WRAPPER(sha512,    sha512, SHA512)
209
DEFINE_TOMCRYPT_WRAPPER(ripemd160, rmd160, RIPEMD160)
210
 
211
static void run_tomcrypt_aes128(uint8_t *output,
212
                                const uint8_t *input, unsigned size)
213
{
214
    symmetric_key aes;
215
    unsigned i;
216
 
217
    aes_setup(hardcoded_key, 16, 0, &aes);
218
    size -= 15;
219
    for (i = 0; i < size; i += 16)
220
        aes_ecb_encrypt(input + i, output + i, &aes);
221
}
222
 
223
#define IMPL_USE_tomcrypt(...) IMPL_USE(__VA_ARGS__)
224
#else
225
#define IMPL_USE_tomcrypt(...) /* ignore */
226
#endif
227
 
228
/***************************************************************************
229
 * Driver code
230
 ***************************************************************************/
231
 
232
static unsigned crc32(const uint8_t *data, unsigned size)
233
{
234
    return av_crc(av_crc_get_table(AV_CRC_32_IEEE), 0, data, size);
235
}
236
 
237
static void run_implementation(const uint8_t *input, uint8_t *output,
238
                               struct hash_impl *impl, unsigned size)
239
{
240
    uint64_t t0, t1;
241
    unsigned nruns = specified_runs ? specified_runs : (1 << 30) / size;
242
    unsigned outlen = 0, outcrc = 0;
243
    unsigned i, j, val;
244
    double mtime, ttime = 0, ttime2 = 0, stime;
245
    uint8_t outref[MAX_OUTPUT_SIZE];
246
 
247
    if (enabled_libs  && !av_stristr(enabled_libs,  impl->lib) ||
248
        enabled_algos && !av_stristr(enabled_algos, impl->name))
249
        return;
250
    if (!sscanf(impl->output, "crc:%x", &outcrc)) {
251
        outlen = strlen(impl->output) / 2;
252
        for (i = 0; i < outlen; i++) {
253
            sscanf(impl->output + i * 2, "%02x", &val);
254
            outref[i] = val;
255
        }
256
    }
257
    for (i = 0; i < 8; i++) /* heat caches */
258
        impl->run(output, input, size);
259
    for (i = 0; i < nruns; i++) {
260
        memset(output, 0, size); /* avoid leftovers from previous runs */
261
        t0 = AV_READ_TIME();
262
        impl->run(output, input, size);
263
        t1 = AV_READ_TIME();
264
        if (outlen ? memcmp(output, outref, outlen) :
265
                     crc32(output, size) != outcrc) {
266
            fprintf(stderr, "Expected: ");
267
            if (outlen)
268
                for (j = 0; j < outlen; j++)
269
                    fprintf(stderr, "%02x", output[j]);
270
            else
271
                fprintf(stderr, "%08x", crc32(output, size));
272
            fprintf(stderr, "\n");
273
            fatal_error("output mismatch");
274
        }
275
        mtime = (double)(t1 - t0) / size;
276
        ttime  += mtime;
277
        ttime2 += mtime * mtime;
278
    }
279
 
280
    ttime  /= nruns;
281
    ttime2 /= nruns;
282
    stime = sqrt(ttime2 - ttime * ttime);
283
    printf("%-10s %-12s size: %7d  runs: %6d  time: %8.3f +- %.3f\n",
284
           impl->lib, impl->name, size, nruns, ttime, stime);
285
    fflush(stdout);
286
}
287
 
288
#define IMPL_USE(lib, name, symbol, output) \
289
    { #lib, name, run_ ## lib ## _ ## symbol, output },
290
#define IMPL(lib, ...) IMPL_USE_ ## lib(lib, __VA_ARGS__)
291
#define IMPL_ALL(...) \
292
    IMPL(lavu,       __VA_ARGS__) \
293
    IMPL(crypto,     __VA_ARGS__) \
294
    IMPL(gcrypt,     __VA_ARGS__) \
295
    IMPL(tomcrypt,   __VA_ARGS__)
296
 
297
struct hash_impl implementations[] = {
298
    IMPL_ALL("MD5",        md5,       "aa26ff5b895356bcffd9292ba9f89e66")
299
    IMPL_ALL("SHA-1",      sha1,      "1fd8bd1fa02f5b0fe916b0d71750726b096c5744")
300
    IMPL_ALL("SHA-256",    sha256,    "14028ac673b3087e51a1d407fbf0df4deeec8f217119e13b07bf2138f93db8c5")
301
    IMPL_ALL("SHA-512",    sha512,    "3afdd44a80d99af15c87bd724cb717243193767835ce866dd5d58c02d674bb57"
302
                                      "7c25b9e118c200a189fcd5a01ef106a4e200061f3e97dbf50ba065745fd46bef")
303
    IMPL_ALL("RIPEMD-160", ripemd160, "62a5321e4fc8784903bb43ab7752c75f8b25af00")
304
    IMPL_ALL("AES-128",    aes128,    "crc:ff6bc888")
305
};
306
 
307
int main(int argc, char **argv)
308
{
309
    uint8_t *input = av_malloc(MAX_INPUT_SIZE * 2);
310
    uint8_t *output = input + MAX_INPUT_SIZE;
311
    unsigned i, impl, size;
312
    int opt;
313
 
314
    while ((opt = getopt(argc, argv, "hl:a:r:")) != -1) {
315
        switch (opt) {
316
        case 'l':
317
            enabled_libs = optarg;
318
            break;
319
        case 'a':
320
            enabled_algos = optarg;
321
            break;
322
        case 'r':
323
            specified_runs = strtol(optarg, NULL, 0);
324
            break;
325
        case 'h':
326
        default:
327
            fprintf(stderr, "Usage: %s [-l libs] [-a algos] [-r runs]\n",
328
                    argv[0]);
329
            if ((USE_EXT_LIBS)) {
330
                char buf[1024];
331
                snprintf(buf, sizeof(buf), "%s%s%s",
332
                         ((USE_EXT_LIBS) & USE_crypto)   ? "+crypto"   : "",
333
                         ((USE_EXT_LIBS) & USE_gcrypt)   ? "+gcrypt"   : "",
334
                         ((USE_EXT_LIBS) & USE_tomcrypt) ? "+tomcrypt" : "");
335
                fprintf(stderr, "Built with the following external libraries:\n"
336
                        "make VERSUS=%s\n", buf + 1);
337
            } else {
338
                fprintf(stderr, "Built without external libraries; use\n"
339
                        "make VERSUS=crypto+gcrypt+tomcrypt tools/crypto_bench\n"
340
                        "to enable them.\n");
341
            }
342
            exit(opt != 'h');
343
        }
344
    }
345
 
346
    if (!input)
347
        fatal_error("out of memory");
348
    for (i = 0; i < MAX_INPUT_SIZE; i += 4)
349
        AV_WB32(input + i, i);
350
 
351
    size = MAX_INPUT_SIZE;
352
    for (impl = 0; impl < FF_ARRAY_ELEMS(implementations); impl++)
353
        run_implementation(input, output, &implementations[impl], size);
354
 
355
    av_free(input);
356
 
357
    return 0;
358
}