2 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
4 * This file is part of Libav.
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libav 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #define FFMIN(a, b) ((a) > (b) ? (b) : (a))
31 uint64_t exp16_table
[21] = {
55 // 16.16 fixpoint log()
56 static int64_t log16(uint64_t a
)
62 return -log16((1LL << 32) / a
);
65 for (i
= 20; i
>= 0; i
--) {
66 int64_t b
= exp16_table
[i
];
70 a
= ((a
/ b
) << 16) + (((a
% b
) << 16) + b
/ 2) / b
;
75 static uint64_t int_sqrt(uint64_t a
)
81 for (s
= 31; s
>= 0; s
--) {
82 uint64_t b
= ret_sq
+ (1ULL << (s
* 2)) + (ret
<< s
) * 2;
91 int main(int argc
, char *argv
[])
99 int len
= argc
< 4 ?
1 : atoi(argv
[3]);
100 int64_t max
= (1 << (8 * len
)) - 1;
101 int shift
= argc
< 5 ?
0 : atoi(argv
[4]);
102 int skip_bytes
= argc
< 6 ?
0 : atoi(argv
[5]);
108 printf("tiny_psnr <file1> <file2> [<elem size> [<shift> [<skip bytes>]]]\n");
109 printf("WAV headers are skipped automatically.\n");
113 f
[0] = fopen(argv
[1], "rb");
114 f
[1] = fopen(argv
[2], "rb");
115 if (!f
[0] || !f
[1]) {
116 fprintf(stderr
, "Could not open input files.\n");
120 for (i
= 0; i
< 2; i
++) {
122 if (fread(p
, 1, 12, f
[i
]) != 12)
124 if (!memcmp(p
, "RIFF", 4) &&
125 !memcmp(p
+ 8, "WAVE", 4)) {
126 if (fread(p
, 1, 8, f
[i
]) != 8)
128 while (memcmp(p
, "data", 4)) {
129 int s
= p
[4] | p
[5] << 8 | p
[6] << 16 | p
[7] << 24;
130 fseek(f
[i
], s
, SEEK_CUR
);
131 if (fread(p
, 1, 8, f
[i
]) != 8)
135 fseek(f
[i
], -12, SEEK_CUR
);
139 fseek(f
[shift
< 0], abs(shift
), SEEK_CUR
);
141 fseek(f
[0], skip_bytes
, SEEK_CUR
);
142 fseek(f
[1], skip_bytes
, SEEK_CUR
);
145 int s0
= fread(buf
[0], 1, SIZE
, f
[0]);
146 int s1
= fread(buf
[1], 1, SIZE
, f
[1]);
148 for (j
= 0; j
< FFMIN(s0
, s1
); j
++) {
149 int64_t a
= buf
[0][j
];
150 int64_t b
= buf
[1][j
];
153 a
= (int16_t)(a
| (buf
[0][++j
] << 8));
154 b
= (int16_t)(b
| (buf
[1][ j
] << 8));
156 sse
+= (a
- b
) * (a
- b
);
167 i
= FFMIN(size0
, size1
) / len
;
170 dev
= int_sqrt(((sse
/ i
) * F
* F
) + (((sse
% i
) * F
* F
) + i
/ 2) / i
);
172 psnr
= ((2 * log16(max
<< 16) + log16(i
) - log16(sse
)) *
173 284619LL * F
+ (1LL << 31)) / (1LL << 32);
175 psnr
= 1000 * F
- 1; // floating point free infinity :)
177 printf("stddev:%5d.%02d PSNR:%3d.%02d MAXDIFF:%5d bytes:%9d/%9d\n",
178 (int)(dev
/ F
), (int)(dev
% F
),
179 (int)(psnr
/ F
), (int)(psnr
% F
),
180 maxdist
, size0
, size1
);