changeset 9809:508dc4231269

Actually do something useful with XVID_GLOBAL_EXTRASTATS / XVID_EXTRASTATS. Now we can really compare XviD and libavcodec :)
author rguyom
date Thu, 03 Apr 2003 06:53:01 +0000
parents a67f1ea3a5d5
children b68bad6e41ad
files DOCS/en/mplayer.1 libmpcodecs/ve_xvid.c
diffstat 2 files changed, 73 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/DOCS/en/mplayer.1	Thu Apr 03 00:52:33 2003 +0000
+++ b/DOCS/en/mplayer.1	Thu Apr 03 06:53:01 2003 +0000
@@ -3243,8 +3243,8 @@
 Note: This has a significant effect on the speed.
 .IPs psnr
 print the psnr (peak signal to noise ratio) for the whole video after encoding
-and store the per frame psnr in a file with a name like 'psnr_012345.log'.
-Return values are in dB (decibel), the higher the better.
+and store the per frame psnr in a file with a name like 'psnr_hhmmss.log'.
+Returned values are in dB (decibel), the higher the better.
 .IPs mpeg_quant
 use MPEG quantizers instead of H.263.
 (default: disabled) (i.e.\& use H.263 quantizers)
@@ -3463,6 +3463,10 @@
 quantizer ratio between B and non B frames, 150=1.50 (default=150)
 .IPs bquant_offset=<-1000\-1000>
 quantizer offset between B and non B frames, 100=1.00 (default=100)
+.IPs psnr
+print the psnr (peak signal to noise ratio) for the whole video after encoding
+and store the per frame psnr in a file with a name like 'psnr_hhmmss.log'.
+Returned values are in dB (decibel), the higher the better.
 .RE
 
 
--- a/libmpcodecs/ve_xvid.c	Thu Apr 03 00:52:33 2003 +0000
+++ b/libmpcodecs/ve_xvid.c	Thu Apr 03 06:53:01 2003 +0000
@@ -2,6 +2,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <math.h>
+
+#if !defined(INFINITY) && defined(HUGE_VAL)
+#define INFINITY HUGE_VAL
+#endif
 
 #include "../config.h"
 #include "../mp_msg.h"
@@ -96,10 +101,11 @@
 static int xvidenc_gmc = 0;
 static int xvidenc_chroma_me = 0;
 static int xvidenc_reduced = 0;
-static int xvidenc_xstat=0;
 static int xvidenc_hqac=0;
 static int xvidenc_vhq=0;
 static int xvidenc_pref=0;
+static int xvidenc_psnr=0;
+static uint64_t xvid_error[3];
 #endif
 
 struct config xvidencopts_conf[] = {
@@ -127,7 +133,7 @@
     { "packed", &xvidenc_packed, CONF_TYPE_FLAG, 0, 0, 1, NULL},
     { "divx5bvop", &xvidenc_divx5bvop, CONF_TYPE_FLAG, 0, 0, 1, NULL},
     //{ "lumi_mask", &xvidenc_lumi_mask, CONF_TYPE_FLAG, 0, 0, 1, NULL},
-    { "extrastat", &xvidenc_xstat, CONF_TYPE_FLAG, 0, 0, 1, NULL},
+    { "psnr", &xvidenc_psnr, CONF_TYPE_FLAG, 0, 0, 1, NULL},
     { "qpel", &xvidenc_qpel, CONF_TYPE_FLAG, 0, 0, 1, NULL},
     { "max_bframes", &xvidenc_max_bframes, CONF_TYPE_INT, CONF_RANGE, 0, 4, NULL},
     { "bquant_ratio", &xvidenc_bquant_ratio, CONF_TYPE_INT, CONF_RANGE, 0, 1000, NULL},
@@ -147,6 +153,8 @@
     XVID_ENC_FRAME enc_frame;
     void* enc_handle;
     vbr_control_t vbr_state;
+    int pixels;
+    int nb_frames;
 };
 
 static int
@@ -224,8 +232,12 @@
 	enc_param.global |= XVID_GLOBAL_PACKED;
     if (xvidenc_reduced)
 	enc_param.global |= XVID_GLOBAL_REDUCED;
-    if (xvidenc_xstat)
+    if (xvidenc_psnr) {
 	enc_param.global |= XVID_GLOBAL_EXTRASTATS;
+	fp->pixels = width * height;
+	fp->nb_frames = 0;
+	xvid_error[0] = xvid_error[1] = xvid_error[2] = 0;
+    }
 #endif
     if (xvidenc_greyscale)
 	enc_param.global |= XVID_GREYSCALE;
@@ -269,7 +281,7 @@
 	fp->enc_frame.general |= XVID_MODEDECISION_BITS;
     if (xvidenc_gmc)
 	fp->enc_frame.general |= XVID_GMC;
-    if (xvidenc_xstat)
+    if (xvidenc_psnr)
 	fp->enc_frame.general |= XVID_EXTRASTATS;
     if (xvidenc_chroma_me)
 	fp->enc_frame.motion |= PMV_CHROMA16 | PMV_CHROMA8;
@@ -350,11 +362,27 @@
     return 1;
 }
 
+static double
+sse_to_PSNR(double sse, double pixels)
+{
+    return sse == 0 ? INFINITY : 4.34294481903251827652 * (11.08252709031685229249 - log(sse/pixels));
+    // 4.34294481903251827652 = 10/log(10)
+    // 11.08252709031685229249 = log(255*255)
+}
+
 static void
 uninit(struct vf_instance_s* vf)
 {
     struct vf_priv_s *fp = vf->priv;
 
+    if (xvidenc_psnr) {
+	double p = (double)fp->pixels * (double)fp->nb_frames;
+        printf ("PSNR: Y:%2.2f, Cb:%2.2f, Cr:%2.2f, All:%2.2f\n", 
+		sse_to_PSNR(xvid_error[0], p), 
+		sse_to_PSNR(xvid_error[1], p/4), 
+		sse_to_PSNR(xvid_error[2], p/4), 
+		sse_to_PSNR(xvid_error[0] + xvid_error[1] + xvid_error[2], p*1.5));
+    }
     vbrFinish(&fp->vbr_state);
 }
 
@@ -433,6 +461,41 @@
 	mp_msg(MSGT_MENCODER, MSGL_ERR, "xvid: failure\n");
 	break;
     }
+
+    if (xvidenc_psnr) {
+        static FILE *fvstats = NULL;
+        char filename[20];
+
+        if (!fvstats) {
+            time_t today2;
+            struct tm *today;
+            today2 = time (NULL);
+            today = localtime (&today2);
+            sprintf (filename, "psnr_%02d%02d%02d.log", today->tm_hour, today->tm_min, today->tm_sec);
+            fvstats = fopen (filename,"w");
+            if (!fvstats) {
+                perror ("fopen");
+                xvidenc_psnr = 0; // disable block
+            }
+        }
+
+	xvid_error[0] += enc_stats.sse_y;
+	xvid_error[1] += enc_stats.sse_u;
+	xvid_error[2] += enc_stats.sse_v;
+
+        fprintf (fvstats, "%6d, %2d, %6d, %2.2f, %2.2f, %2.2f, %2.2f %c\n",
+		 fp->nb_frames,
+		 enc_stats.quant,
+		 fp->enc_frame.length,
+		 sse_to_PSNR (enc_stats.sse_y, fp->pixels),
+		 sse_to_PSNR (enc_stats.sse_u, fp->pixels / 4),
+		 sse_to_PSNR (enc_stats.sse_v, fp->pixels / 4),
+		 sse_to_PSNR (enc_stats.sse_y + enc_stats.sse_u + enc_stats.sse_v, (double)fp->pixels * 1.5),
+		 fp->enc_frame.intra == 0 ? 'P' : fp->enc_frame.intra == 1 ? 'I' : 'B'
+		 );
+
+	fp->nb_frames++;
+    }
     
     // write output
     muxer_write_chunk(fp->mux, fp->enc_frame.length, fp->enc_frame.intra==1 ? 0x10 : 0);