[FFmpeg-devel] [PATCH] libavfilter: created a new filter that obtains the average peak signal-to-noise ratio (PSNR) of two input video files in YUV format.
Michael Niedermayer
michaelni at gmx.at
Mon Jul 18 11:36:07 CEST 2011
On Mon, Jul 04, 2011 at 07:22:26PM +0200, Stefano Sabatini wrote:
> On date Thursday 2011-06-23 14:57:59 +0200, Stefano Sabatini encoded:
> > On date Thursday 2011-06-23 14:07:51 +0200, Roger Pau Monné encoded:
> > > 2011/6/23 Stefano Sabatini <stefano.sabatini-lala at poste.it>:
> > > > On date Tuesday 2011-06-21 16:01:36 +0200, Stefano Sabatini encoded:
> > > >> On date Tuesday 2011-06-21 14:44:50 +0200, Roger Pau Monné encoded:
> > > >> > Hello,
> > > >> >
[..]
> +static inline int pow2(int base)
> +{
> + return base*base;
> +}
> +
> +static inline double get_psnr(double mse, int nb_frames, int max)
> +{
> + return 10.0*log((pow2(max))/(mse/nb_frames))/log(10.0);
> +}
> +
> +static inline
> +void compute_images_mse(const uint8_t *ref_data[4],
> + const uint8_t *data[4], const int linesizes[4],
> + int w, int h, const AVPixFmtDescriptor *desc,
> + double mse[4], uint16_t *line1, uint16_t *line2)
> +{
> + int i, c, j = w;
> +
> + memset(mse, 0, sizeof(*mse)*4);
> +
> + for (c = 0; c < desc->nb_components; c++) {
> + int w1 = c == 1 || c == 2 ? w>>desc->log2_chroma_w : w;
> + int h1 = c == 1 || c == 2 ? h>>desc->log2_chroma_h : h;
> +
> + for (i = 0; i < h1; i++) {
> + av_read_image_line(line1, ref_data, linesizes, desc, 0, i, c, w1, 0);
> + av_read_image_line(line2, data, linesizes, desc, 0, i, c, w1, 0);
> + for (j = 0; j < w1; j++)
> + mse[c] += pow2(line1[j] - line2[j]);
> + }
> + mse[c] /= w1*h1;
> + }
> +}
This is a bit slow, i think there should be specific optimized code
for planar yuv as its most common.
also id avoid the int->double per sample and sum all samples of a
line (or each 100 samples) in 32bit int and only after that change to
a type with more range
[...]
> +static int config_input_ref(AVFilterLink *inlink)
> +{
> + AVFilterContext *ctx = inlink->dst;
> + PSNRContext *psnr = ctx->priv;
> +
> + if (ctx->inputs[0]->w != ctx->inputs[1]->w ||
> + ctx->inputs[0]->h != ctx->inputs[1]->h) {
> + av_log(ctx, AV_LOG_ERROR,
> + "Width and/or heigth of input videos are different, could not calculate PSNR\n");
> + return AVERROR(EINVAL);
> + }
> + if (ctx->inputs[0]->format != ctx->inputs[1]->format) {
> + av_log(ctx, AV_LOG_ERROR,
> + "Input filters have different pixel formats, could not calculate PSNR\n");
> + return AVERROR(EINVAL);
> + }
> +
> + if (!(psnr->line1 = av_malloc(sizeof(*psnr->line1) * inlink->w)) ||
> + !(psnr->line2 = av_malloc(sizeof(*psnr->line2) * inlink->w)))
> + return AVERROR(ENOMEM);
> +
> + switch (inlink->format) {
> + case PIX_FMT_YUV410P:
> + case PIX_FMT_YUV411P:
> + case PIX_FMT_YUV420P:
> + case PIX_FMT_YUV422P:
> + case PIX_FMT_YUV440P:
> + case PIX_FMT_YUV444P:
> + case PIX_FMT_YUVA420P:
> + psnr->max[0] = 235;
> + psnr->max[3] = 255;
> + psnr->max[1] = psnr->max[2] = 240;
> + break;
> + default:
> + psnr->max[0] = psnr->max[1] = psnr->max[2] = psnr->max[3] = 255;
> + }
> +
> + if (ff_fmt_is_in(inlink->format, yuv_pix_fmts)) psnr->is_yuv = 1;
> + else if (ff_fmt_is_in(inlink->format, rgb_pix_fmts)) psnr->is_rgb = 1;
> +
> + if (psnr->is_rgb) {
> + switch (inlink->format) {
> + case PIX_FMT_ARGB: psnr->rgba_map[A] = 0; psnr->rgba_map[R] = 1; psnr->rgba_map[G] = 2; psnr->rgba_map[B] = 3; break;
> + case PIX_FMT_ABGR: psnr->rgba_map[A] = 0; psnr->rgba_map[B] = 1; psnr->rgba_map[G] = 2; psnr->rgba_map[R] = 3; break;
> + case PIX_FMT_RGBA:
> + case PIX_FMT_RGB24: psnr->rgba_map[R] = 0; psnr->rgba_map[G] = 1; psnr->rgba_map[B] = 2; psnr->rgba_map[A] = 3; break;
> + case PIX_FMT_BGRA:
> + case PIX_FMT_BGR24: psnr->rgba_map[B] = 0; psnr->rgba_map[G] = 1; psnr->rgba_map[R] = 2; psnr->rgba_map[A] = 3; break;
> + }
> + }
> +
> + for(int j = 0; j < av_pix_fmt_descriptors[inlink->format].nb_components; j++)
> + psnr->average_max += psnr->max[j];
> + psnr->average_max /= av_pix_fmt_descriptors[inlink->format].nb_components;
the 3 planes mse should be rescaled before adding them together
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
If you think the mosad wants you dead since a long time then you are either
wrong or dead since a long time.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20110718/6b21468f/attachment.asc>
More information about the ffmpeg-devel
mailing list