changeset 252:ddb1a0e94cf4 libavcodec

- Added PSNR feature to libavcodec and ffmpeg. By now just Y PSNR until I'm sure it works ok. Also it's slow, so use it only when you _really_ need to measure quality. - Fix libavcodec Makefile to enable profiling.
author pulento
date Tue, 26 Feb 2002 22:14:27 +0000
parents 75091bfc577b
children 4448dd55d415
files Makefile avcodec.h dsputil.c dsputil.h i386/mpegvideo_mmx.c mpegvideo.c
diffstat 6 files changed, 66 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri Feb 22 19:19:01 2002 +0000
+++ b/Makefile	Tue Feb 26 22:14:27 2002 +0000
@@ -16,6 +16,11 @@
        libac3/imdct.o  libac3/parse.o
 endif
 
+ifeq ($(TARGET_GPROF),yes)
+CFLAGS+=-p
+LDFLAGS+=-p
+endif
+
 # i386 mmx specific stuff
 ifeq ($(TARGET_MMX),yes)
 OBJS += i386/fdct_mmx.o i386/cputest.o \
--- a/avcodec.h	Fri Feb 22 19:19:01 2002 +0000
+++ b/avcodec.h	Tue Feb 26 22:14:27 2002 +0000
@@ -123,6 +123,12 @@
     /* with a Start Code (it should) H.263 does   */
     void (*rtp_callback)(void *data, int size, int packet_number); 
 
+    /* These are for PSNR calculation, if you set get_psnr to 1 */
+    /* after encoding you will have the PSNR on psnr_y/cb/cr    */
+    int get_psnr;
+    float psnr_y;
+    float psnr_cb;
+    float psnr_cr;
                  
     /* the following fields are ignored */
     void *opaque;   /* can be used to carry app specific stuff */
--- a/dsputil.c	Fri Feb 22 19:19:01 2002 +0000
+++ b/dsputil.c	Tue Feb 26 22:14:27 2002 +0000
@@ -18,6 +18,7 @@
  */
 #include <stdlib.h>
 #include <stdio.h>
+#include <math.h>
 #include "avcodec.h"
 #include "dsputil.h"
 #include "simple_idct.h"
@@ -576,3 +577,37 @@
     
     build_zigzag_end();
 }
+
+void get_psnr(UINT8 *orig_image[3], UINT8 *coded_image[3],
+              int orig_linesize[3], int coded_linesize,
+              AVCodecContext *avctx)
+{
+    int quad, diff, x, y;
+    UINT8 *orig, *coded;
+    UINT32 *sq = squareTbl + 256;
+    
+    quad = 0;
+    diff = 0;
+    
+    /* Luminance */
+    orig = orig_image[0];
+    coded = coded_image[0];
+    
+    for (y=0;y<avctx->height;y++) {
+        for (x=0;x<avctx->width;x++) {
+            diff = *(orig + x) - *(coded + x);
+            quad += sq[diff];
+        }
+        orig += orig_linesize[0];
+        coded += coded_linesize;
+    }
+   
+    avctx->psnr_y = (float) quad / (float) (avctx->width * avctx->height);
+    
+    if (avctx->psnr_y) {
+        avctx->psnr_y = (float) (255 * 255) / avctx->psnr_y;
+        avctx->psnr_y = 10 * (float) log10 (avctx->psnr_y); 
+    } else
+        avctx->psnr_y = 99.99;
+}
+
--- a/dsputil.h	Fri Feb 22 19:19:01 2002 +0000
+++ b/dsputil.h	Tue Feb 26 22:14:27 2002 +0000
@@ -2,6 +2,7 @@
 #define DSPUTIL_H
 
 #include "common.h"
+#include "avcodec.h"
 
 /* dct code */
 typedef short DCTELEM;
@@ -138,4 +139,9 @@
 
 #endif
 
+/* PSNR */
+void get_psnr(UINT8 *orig_image[3], UINT8 *coded_image[3],
+              int orig_linesize[3], int coded_linesize,
+              AVCodecContext *avctx);
+              
 #endif
--- a/i386/mpegvideo_mmx.c	Fri Feb 22 19:19:01 2002 +0000
+++ b/i386/mpegvideo_mmx.c	Tue Feb 26 22:14:27 2002 +0000
@@ -96,14 +96,14 @@
                 block[0] = block[0] * s->c_dc_scale;
         }
         for(i=1; i<8; i++) {
-    	    level = block[i];
-	        if (level) {
-		        if (level < 0) {
-			        level = level * qmul - qadd;
-		        } else {
-			        level = level * qmul + qadd;
-		        }
-		        block[i] = level;
+            level = block[i];
+            if (level) {
+    	        if (level < 0) {
+                    level = level * qmul - qadd;
+                } else {
+                    level = level * qmul + qadd;
+                }
+                block[i] = level;
             }
         }
         nCoeffs=64;
--- a/mpegvideo.c	Fri Feb 22 19:19:01 2002 +0000
+++ b/mpegvideo.c	Tue Feb 26 22:14:27 2002 +0000
@@ -522,6 +522,12 @@
     s->total_bits += (pbBufPtr(&s->pb) - s->pb.buf) * 8;
 
     avctx->quality = s->qscale;
+    if (avctx->get_psnr) {
+        /* At this point pict->data should have the original frame   */
+        /* an s->current_picture should have the coded/decoded frame */
+        get_psnr(pict->data, s->current_picture,
+                 pict->linesize, s->linesize, avctx);
+    }
     return pbBufPtr(&s->pb) - s->pb.buf;
 }