32
33
#include "drawutils.h"
33
34
#include "formats.h"
34
35
#include "internal.h"
37
39
typedef struct PSNRContext {
38
40
const AVClass *class;
39
41
FFDualInputContext dinput;
40
double mse, min_mse, max_mse;
42
double mse, min_mse, max_mse, mse_comp[4];
41
43
uint64_t nb_frames;
43
45
char *stats_file_str;
50
52
int planeheight[4];
52
void (*compute_mse)(struct PSNRContext *s,
53
const uint8_t *m[4], const int ml[4],
54
const uint8_t *r[4], const int rl[4],
55
int w, int h, double mse[4]);
53
double planeweight[4];
58
57
#define OFFSET(x) offsetof(PSNRContext, x)
76
75
return 10.0 * log(pow2(max) / (mse / nb_frames)) / log(10.0);
78
static uint64_t sse_line_8bit(const uint8_t *main_line, const uint8_t *ref_line, int outw)
83
for (j = 0; j < outw; j++)
84
m2 += pow2(main_line[j] - ref_line[j]);
89
static uint64_t sse_line_16bit(const uint8_t *_main_line, const uint8_t *_ref_line, int outw)
93
const uint16_t *main_line = (const uint16_t *) _main_line;
94
const uint16_t *ref_line = (const uint16_t *) _ref_line;
96
for (j = 0; j < outw; j++)
97
m2 += pow2(main_line[j] - ref_line[j]);
80
103
void compute_images_mse(PSNRContext *s,
81
104
const uint8_t *main_data[4], const int main_linesizes[4],
82
105
const uint8_t *ref_data[4], const int ref_linesizes[4],
83
106
int w, int h, double mse[4])
87
110
for (c = 0; c < s->nb_components; c++) {
88
111
const int outw = s->planewidth[c];
92
115
const int ref_linesize = ref_linesizes[c];
93
116
const int main_linesize = main_linesizes[c];
96
for (i = 0; i < outh; i++) {
98
for (j = 0; j < outw; j++)
99
m2 += pow2(main_line[j] - ref_line[j]);
101
ref_line += ref_linesize;
102
main_line += main_linesize;
104
mse[c] = m / (double)(outw * outh);
109
void compute_images_mse_16bit(PSNRContext *s,
110
const uint8_t *main_data[4], const int main_linesizes[4],
111
const uint8_t *ref_data[4], const int ref_linesizes[4],
112
int w, int h, double mse[4])
116
for (c = 0; c < s->nb_components; c++) {
117
const int outw = s->planewidth[c];
118
const int outh = s->planeheight[c];
119
const uint16_t *main_line = (uint16_t *)main_data[c];
120
const uint16_t *ref_line = (uint16_t *)ref_data[c];
121
const int ref_linesize = ref_linesizes[c] / 2;
122
const int main_linesize = main_linesizes[c] / 2;
125
for (i = 0; i < outh; i++) {
126
for (j = 0; j < outw; j++)
127
m += pow2(main_line[j] - ref_line[j]);
118
for (i = 0; i < outh; i++) {
119
m += s->dsp.sse_line(main_line, ref_line, outw);
128
120
ref_line += ref_linesize;
129
121
main_line += main_linesize;
154
146
AVDictionary **metadata = avpriv_frame_get_metadatap(main);
156
s->compute_mse(s, (const uint8_t **)main->data, main->linesize,
157
(const uint8_t **)ref->data, ref->linesize,
158
main->width, main->height, comp_mse);
148
compute_images_mse(s, (const uint8_t **)main->data, main->linesize,
149
(const uint8_t **)ref->data, ref->linesize,
150
main->width, main->height, comp_mse);
160
152
for (j = 0; j < s->nb_components; j++)
162
mse /= s->nb_components;
153
mse += comp_mse[j] * s->planeweight[j];
164
155
s->min_mse = FFMIN(s->min_mse, mse);
165
156
s->max_mse = FFMAX(s->max_mse, mse);
159
for (j = 0; j < s->nb_components; j++)
160
s->mse_comp[j] += comp_mse[j];
170
163
for (j = 0; j < s->nb_components; j++) {
171
164
c = s->is_rgb ? s->rgba_map[j] : j;
172
165
set_meta(metadata, "lavfi.psnr.mse.", s->comps[j], comp_mse[c]);
173
set_meta(metadata, "lavfi.psnr.mse_avg", 0, mse);
174
166
set_meta(metadata, "lavfi.psnr.psnr.", s->comps[j], get_psnr(comp_mse[c], 1, s->max[c]));
175
set_meta(metadata, "lavfi.psnr.psnr_avg", 0, get_psnr(mse, 1, s->average_max));
168
set_meta(metadata, "lavfi.psnr.mse_avg", 0, mse);
169
set_meta(metadata, "lavfi.psnr.psnr_avg", 0, get_psnr(mse, 1, s->average_max));
178
171
if (s->stats_file) {
179
172
fprintf(s->stats_file, "n:%"PRId64" mse_avg:%0.2f ", s->nb_frames, mse);
181
174
c = s->is_rgb ? s->rgba_map[j] : j;
182
175
fprintf(s->stats_file, "mse_%c:%0.2f ", s->comps[j], comp_mse[c]);
177
fprintf(s->stats_file, "psnr_avg:%0.2f ", get_psnr(mse, 1, s->average_max));
184
178
for (j = 0; j < s->nb_components; j++) {
185
179
c = s->is_rgb ? s->rgba_map[j] : j;
186
180
fprintf(s->stats_file, "psnr_%c:%0.2f ", s->comps[j],
256
251
return AVERROR(EINVAL);
259
switch (inlink->format) {
260
case AV_PIX_FMT_GRAY8:
261
case AV_PIX_FMT_GRAY16:
262
case AV_PIX_FMT_GBRP:
263
case AV_PIX_FMT_GBRP9:
264
case AV_PIX_FMT_GBRP10:
265
case AV_PIX_FMT_GBRP12:
266
case AV_PIX_FMT_GBRP14:
267
case AV_PIX_FMT_GBRP16:
268
case AV_PIX_FMT_GBRAP:
269
case AV_PIX_FMT_GBRAP16:
270
case AV_PIX_FMT_YUVJ411P:
271
case AV_PIX_FMT_YUVJ420P:
272
case AV_PIX_FMT_YUVJ422P:
273
case AV_PIX_FMT_YUVJ440P:
274
case AV_PIX_FMT_YUVJ444P:
275
s->max[0] = (1 << (desc->comp[0].depth_minus1 + 1)) - 1;
276
s->max[1] = (1 << (desc->comp[1].depth_minus1 + 1)) - 1;
277
s->max[2] = (1 << (desc->comp[2].depth_minus1 + 1)) - 1;
278
s->max[3] = (1 << (desc->comp[3].depth_minus1 + 1)) - 1;
281
s->max[0] = 235 * (1 << (desc->comp[0].depth_minus1 - 7));
282
s->max[1] = 240 * (1 << (desc->comp[1].depth_minus1 - 7));
283
s->max[2] = 240 * (1 << (desc->comp[2].depth_minus1 - 7));
284
s->max[3] = (1 << (desc->comp[3].depth_minus1 + 1)) - 1;
254
s->max[0] = (1 << (desc->comp[0].depth_minus1 + 1)) - 1;
255
s->max[1] = (1 << (desc->comp[1].depth_minus1 + 1)) - 1;
256
s->max[2] = (1 << (desc->comp[2].depth_minus1 + 1)) - 1;
257
s->max[3] = (1 << (desc->comp[3].depth_minus1 + 1)) - 1;
287
259
s->is_rgb = ff_fill_rgba_map(s->rgba_map, inlink->format) >= 0;
288
260
s->comps[0] = s->is_rgb ? 'r' : 'y' ;
290
262
s->comps[2] = s->is_rgb ? 'b' : 'v' ;
291
263
s->comps[3] = 'a';
293
for (j = 0; j < s->nb_components; j++)
294
s->average_max += s->max[j];
295
s->average_max /= s->nb_components;
297
265
s->planeheight[1] = s->planeheight[2] = FF_CEIL_RSHIFT(inlink->h, desc->log2_chroma_h);
298
266
s->planeheight[0] = s->planeheight[3] = inlink->h;
299
267
s->planewidth[1] = s->planewidth[2] = FF_CEIL_RSHIFT(inlink->w, desc->log2_chroma_w);
300
268
s->planewidth[0] = s->planewidth[3] = inlink->w;
270
for (j = 0; j < s->nb_components; j++)
271
sum += s->planeheight[j] * s->planewidth[j];
272
for (j = 0; j < s->nb_components; j++) {
273
s->planeweight[j] = (double) s->planeheight[j] * s->planewidth[j] / sum;
274
s->average_max += s->max[j] * s->planeweight[j];
302
s->compute_mse = desc->comp[0].depth_minus1 > 7 ? compute_images_mse_16bit : compute_images_mse;
277
s->dsp.sse_line = desc->comp[0].depth_minus1 > 7 ? sse_line_16bit : sse_line_8bit;
279
ff_psnr_init_x86(&s->dsp, desc->comp[0].depth_minus1 + 1);
339
316
PSNRContext *s = ctx->priv;
341
318
if (s->nb_frames > 0) {
342
av_log(ctx, AV_LOG_INFO, "PSNR average:%0.2f min:%0.2f max:%0.2f\n",
323
for (j = 0; j < s->nb_components; j++) {
324
int c = s->is_rgb ? s->rgba_map[j] : j;
325
av_strlcatf(buf, sizeof(buf), " %c:%0.2f", s->comps[j],
326
get_psnr(s->mse_comp[c], s->nb_frames, s->max[c]));
328
av_log(ctx, AV_LOG_INFO, "PSNR%s average:%0.2f min:%0.2f max:%0.2f\n",
343
330
get_psnr(s->mse, s->nb_frames, s->average_max),
344
331
get_psnr(s->max_mse, 1, s->average_max),
345
332
get_psnr(s->min_mse, 1, s->average_max));