- 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
This commit is contained in:
parent
2b9ab1d54a
commit
43f1708f8b
10
ffmpeg.c
10
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, },
|
||||
};
|
||||
|
@ -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 \
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user