aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuanjo <pulento@users.sourceforge.net>2002-02-26 22:14:27 +0000
committerJuanjo <pulento@users.sourceforge.net>2002-02-26 22:14:27 +0000
commit43f1708f8bb400790b226993ab1e6c3d12564d3b (patch)
treecb98d6f57b9964653dfc407897d0081429d572f2
parent2b9ab1d54a35f7d689b2396cfc59f9dbdcae391f (diff)
downloadffmpeg-43f1708f8bb400790b226993ab1e6c3d12564d3b.tar.gz
- 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. Originally committed as revision 314 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--ffmpeg.c10
-rw-r--r--libavcodec/Makefile5
-rw-r--r--libavcodec/avcodec.h6
-rw-r--r--libavcodec/dsputil.c35
-rw-r--r--libavcodec/dsputil.h6
-rw-r--r--libavcodec/i386/mpegvideo_mmx.c16
-rw-r--r--libavcodec/mpegvideo.c6
7 files changed, 76 insertions, 8 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index 80b1127d7b..5d5431cf26 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -98,6 +98,7 @@ static char *str_comment = NULL;
static int do_benchmark = 0;
static int do_hex_dump = 0;
static int do_play = 0;
+static int do_psnr = 0;
typedef struct AVOutputStream {
int file_index; /* file index */
@@ -958,6 +959,8 @@ static int av_encode(AVFormatContext **output_files,
frame_number = ist->frame_number;
sprintf(buf + strlen(buf), "frame=%5d q=%2d ",
frame_number, enc->quality);
+ if (do_psnr)
+ sprintf(buf + strlen(buf), "PSNR=%6.2f ", enc->psnr_y);
vid = 1;
}
/* compute min pts value */
@@ -1006,6 +1009,8 @@ static int av_encode(AVFormatContext **output_files,
frame_number = ist->frame_number;
sprintf(buf + strlen(buf), "frame=%5d q=%2d ",
frame_number, enc->quality);
+ if (do_psnr)
+ sprintf(buf + strlen(buf), "PSNR=%6.2f ", enc->psnr_y);
vid = 1;
}
/* compute min pts value */
@@ -1618,6 +1623,10 @@ void opt_output_file(const char *filename)
video_enc->flags |= CODEC_FLAG_QSCALE;
video_enc->quality = video_qscale;
}
+ if (do_psnr)
+ video_enc->get_psnr = 1;
+ else
+ video_enc->get_psnr = 0;
/* XXX: need to find a way to set codec parameters */
if (oc->format == &ppm_format ||
oc->format == &ppmpipe_format) {
@@ -1960,6 +1969,7 @@ const OptionDef options[] = {
"add timings for benchmarking" },
{ "hex", OPT_BOOL | OPT_EXPERT, {(void*)&do_hex_dump},
"dump each input packet" },
+ { "psnr", OPT_BOOL | OPT_EXPERT, {(void*)&do_psnr}, "calculate PSNR of compressed frames" },
{ NULL, },
};
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 4898e86a55..fe124a4a1c 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -16,6 +16,11 @@ OBJS+= ac3dec.o \
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 \
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index cc374c1cab..d8abfded9b 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -123,6 +123,12 @@ typedef struct AVCodecContext {
/* 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 */
diff --git a/libavcodec/dsputil.c b/libavcodec/dsputil.c
index 701cb9969a..09c4c231fe 100644
--- a/libavcodec/dsputil.c
+++ b/libavcodec/dsputil.c
@@ -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 @@ void dsputil_init(void)
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;
+}
+
diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
index bb57b09433..ed264c83b7 100644
--- a/libavcodec/dsputil.h
+++ b/libavcodec/dsputil.h
@@ -2,6 +2,7 @@
#define DSPUTIL_H
#include "common.h"
+#include "avcodec.h"
/* dct code */
typedef short DCTELEM;
@@ -138,4 +139,9 @@ void dsputil_init_alpha(void);
#endif
+/* PSNR */
+void get_psnr(UINT8 *orig_image[3], UINT8 *coded_image[3],
+ int orig_linesize[3], int coded_linesize,
+ AVCodecContext *avctx);
+
#endif
diff --git a/libavcodec/i386/mpegvideo_mmx.c b/libavcodec/i386/mpegvideo_mmx.c
index 017e3d4881..f23bdd827a 100644
--- a/libavcodec/i386/mpegvideo_mmx.c
+++ b/libavcodec/i386/mpegvideo_mmx.c
@@ -96,14 +96,14 @@ static void dct_unquantize_h263_mmx(MpegEncContext *s,
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;
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 7c866b794d..6c4e372e1a 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -522,6 +522,12 @@ int MPV_encode_picture(AVCodecContext *avctx,
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;
}