# HG changeset patch # User michaelni # Date 1039036382 0 # Node ID 8ae1e4c24e91cb9acf06fc575a8a5c25e8ffd032 # Parent 2ac4caad5ca6c65231df019a02f2251960b1718e new PSNR code (now works with chroma, b frames, ...) rename *_TYPE to FF_*_TYPE for the external API allow user specified pict_type diff -r 2ac4caad5ca6 -r 8ae1e4c24e91 avcodec.h --- a/avcodec.h Wed Dec 04 12:42:25 2002 +0000 +++ b/avcodec.h Wed Dec 04 21:13:02 2002 +0000 @@ -5,8 +5,8 @@ #define LIBAVCODEC_VERSION_INT 0x000406 #define LIBAVCODEC_VERSION "0.4.6" -#define LIBAVCODEC_BUILD 4642 -#define LIBAVCODEC_BUILD_STR "4642" +#define LIBAVCODEC_BUILD 4643 +#define LIBAVCODEC_BUILD_STR "4643" enum CodecID { CODEC_ID_NONE, @@ -140,6 +140,7 @@ #define CODEC_FLAG_EXTERN_HUFF 0x1000 /* use external huffman table (for mjpeg) */ #define CODEC_FLAG_GRAY 0x2000 /* only decode/encode grayscale */ #define CODEC_FLAG_EMU_EDGE 0x4000/* dont draw edges */ +#define CODEC_FLAG_PSNR 0x8000 /* error[?] variables will be set during encoding */ #define CODEC_FLAG_TRUNCATED 0x00010000 /* input bitstream might be truncated at a random location instead of only at frame boundaries */ #define CODEC_FLAG_NORMALIZE_AQP 0x00020000 /* normalize adaptive quantization */ @@ -252,12 +253,18 @@ * decoding: set by user\ */\ void *opaque;\ +\ + /**\ + * error\ + * encoding: set by lavc if flags&CODEC_FLAG_PSNR\ + * decoding: unused\ + */\ + uint64_t error[4];\ -/* FIXME: these should have FF_ */ -#define I_TYPE 1 // Intra -#define P_TYPE 2 // Predicted -#define B_TYPE 3 // Bi-dir predicted -#define S_TYPE 4 // S(GMC)-VOP MPEG4 +#define FF_I_TYPE 1 // Intra +#define FF_P_TYPE 2 // Predicted +#define FF_B_TYPE 3 // Bi-dir predicted +#define FF_S_TYPE 4 // S(GMC)-VOP MPEG4 typedef struct AVVideoFrame { FF_COMMON_PICTURE @@ -464,17 +471,6 @@ /* with a Start Code (it should) H.263 does */ void (*rtp_callback)(void *data, int size, int packet_number); - /** - * if you set get_psnr to 1 then after encoding you will have the - * PSNR on psnr_y/cb/cr - * encoding: set by user (1-> on, 0-> off) - * decoding: unused - */ - int get_psnr; - float psnr_y; - float psnr_cb; - float psnr_cr; - /* statistics, used for 2-pass encoding */ int mv_bits; int header_bits; @@ -826,6 +822,13 @@ #define FF_DEBUG_QP 16 #define FF_DEBUG_MV 32 #define FF_DEBUG_VIS_MV 64 + + /** + * error + * encoding: set by lavc if flags&CODEC_FLAG_PSNR + * decoding: unused + */ + uint64_t error[4]; } AVCodecContext; typedef struct AVCodec { diff -r 2ac4caad5ca6 -r 8ae1e4c24e91 dsputil.c --- a/dsputil.c Wed Dec 04 12:42:25 2002 +0000 +++ b/dsputil.c Wed Dec 04 21:13:02 2002 +0000 @@ -1528,37 +1528,3 @@ // dsputil_set_bit_exact_mmx(); #endif } - -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;yheight;y++) { - for (x=0;xwidth;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 -r 2ac4caad5ca6 -r 8ae1e4c24e91 huffyuv.c --- a/huffyuv.c Wed Dec 04 12:42:25 2002 +0000 +++ b/huffyuv.c Wed Dec 04 21:13:02 2002 +0000 @@ -461,7 +461,7 @@ s->version=2; avctx->coded_picture= &s->picture; - s->picture.pict_type= I_TYPE; + s->picture.pict_type= FF_I_TYPE; s->picture.key_frame= 1; switch(avctx->pix_fmt){ diff -r 2ac4caad5ca6 -r 8ae1e4c24e91 mpegvideo.c --- a/mpegvideo.c Wed Dec 04 12:42:25 2002 +0000 +++ b/mpegvideo.c Wed Dec 04 21:13:02 2002 +0000 @@ -985,22 +985,50 @@ /* set next picture types & ordering */ if(s->reordered_input_picture[0]==NULL && s->input_picture[0]){ - if(/*s->picture_in_gop_number >= s->gop_size ||*/ s->next_picture.data[0]==NULL || s->intra_only){ - s->reordered_input_picture[0]= s->input_picture[0]; - s->reordered_input_picture[0]->pict_type= I_TYPE; - s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + if(s->input_picture[0]->pict_type){ + /* user selected pict_type */ + if(s->input_picture[0]->pict_type == I_TYPE){ + s->reordered_input_picture[0]= s->input_picture[0]; + s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + }else{ + int b_frames; + + for(b_frames=0; b_framesmax_b_frames+1; b_frames++){ + if(s->input_picture[b_frames]->pict_type!=B_TYPE) break; + } + + if(b_frames > s->max_b_frames){ + fprintf(stderr, "warning, too many bframes in a row\n"); + b_frames = s->max_b_frames; + s->input_picture[b_frames]->pict_type= I_TYPE; + } + + s->reordered_input_picture[0]= s->input_picture[b_frames]; + s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + for(i=0; ireordered_input_picture[i+1]= s->input_picture[i]; + s->reordered_input_picture[i+1]->coded_picture_number= coded_pic_num; + } + } }else{ - s->reordered_input_picture[0]= s->input_picture[s->max_b_frames]; - if(s->picture_in_gop_number + s->max_b_frames >= s->gop_size) + if(/*s->picture_in_gop_number >= s->gop_size ||*/ s->next_picture.data[0]==NULL || s->intra_only){ + s->reordered_input_picture[0]= s->input_picture[0]; s->reordered_input_picture[0]->pict_type= I_TYPE; - else - s->reordered_input_picture[0]->pict_type= P_TYPE; - s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; - for(i=0; imax_b_frames; i++){ - coded_pic_num++; - s->reordered_input_picture[i+1]= s->input_picture[i]; - s->reordered_input_picture[i+1]->pict_type= B_TYPE; - s->reordered_input_picture[i+1]->coded_picture_number= coded_pic_num; + s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + }else{ + s->reordered_input_picture[0]= s->input_picture[s->max_b_frames]; + if(s->picture_in_gop_number + s->max_b_frames >= s->gop_size) + s->reordered_input_picture[0]->pict_type= I_TYPE; + else + s->reordered_input_picture[0]->pict_type= P_TYPE; + s->reordered_input_picture[0]->coded_picture_number= coded_pic_num; + for(i=0; imax_b_frames; i++){ + coded_pic_num++; + s->reordered_input_picture[i+1]= s->input_picture[i]; + s->reordered_input_picture[i+1]->pict_type= B_TYPE; + s->reordered_input_picture[i+1]->coded_picture_number= coded_pic_num; + } } } } @@ -1027,6 +1055,7 @@ { MpegEncContext *s = avctx->priv_data; AVVideoFrame *pic_arg = data; + int i; init_put_bits(&s->pb, buf, buf_size, NULL, NULL); @@ -1076,28 +1105,11 @@ s->total_bits += s->frame_bits; avctx->frame_bits = s->frame_bits; -//printf("fcode: %d, type: %d, head: %d, mv: %d, misc: %d, frame: %d, itex: %d, ptex: %d\n", -//s->f_code, avctx->key_frame, s->header_bits, s->mv_bits, s->misc_bits, s->frame_bits, s->i_tex_bits, s->p_tex_bits); -#if 0 //dump some stats to stats.txt for testing/debuging -if(s->max_b_frames==0) -{ - static FILE *f=NULL; - if(!f) f= fopen("stats.txt", "wb"); - get_psnr(pict->data, s->current_picture, - pict->linesize, s->linesize, avctx); - fprintf(f, "%7d, %7d, %2.4f\n", pbBufPtr(&s->pb) - s->pb.buf, s->qscale, avctx->psnr_y); -} -#endif -#if 0 - 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.data, - pict->linesize, s->linesize, avctx); -// printf("%f\n", avctx->psnr_y); + + for(i=0; i<4; i++){ + avctx->error[i] += s->current_picture.error[i]; } -#endif - + return pbBufPtr(&s->pb) - s->pb.buf; } @@ -1819,7 +1831,7 @@ } } - if (!(s->encoding && (s->intra_only || s->pict_type==B_TYPE))) { + if ((s->flags&CODEC_FLAG_PSNR) || !(s->encoding && (s->intra_only || s->pict_type==B_TYPE))) { //FIXME precalc UINT8 *dest_y, *dest_cb, *dest_cr; int dct_linesize, dct_offset; op_pixels_func (*op_pix)[4]; @@ -2544,6 +2556,22 @@ copy_context_after_encode(best, s, type); } } + +static inline int sse(MpegEncContext *s, uint8_t *src1, uint8_t *src2, int w, int h, int stride){ + uint32_t *sq = squareTbl + 256; + int acc=0; + int x,y; + + if(w==16 && h==16) + return s->dsp.pix_norm(src1, src2, stride); + + for(y=0; yb_count=0; s->skip_count=0; - /* init last dc values */ - /* note: quant matrix value (8) is implied here */ - s->last_dc[0] = 128; - s->last_dc[1] = 128; - s->last_dc[2] = 128; + for(i=0; i<3; i++){ + /* init last dc values */ + /* note: quant matrix value (8) is implied here */ + s->last_dc[i] = 128; + + s->current_picture.error[i] = 0; + } s->mb_incr = 1; s->last_mv[0][0][0] = 0; s->last_mv[0][0][1] = 0; @@ -2992,6 +3022,30 @@ } MPV_decode_mb(s, s->block); + + if(s->flags&CODEC_FLAG_PSNR){ + int w= 16; + int h= 16; + + if(s->mb_x*16 + 16 > s->width ) w= s->width - s->mb_x*16; + if(s->mb_y*16 + 16 > s->height) h= s->height- s->mb_y*16; + + s->current_picture.error[0] += sse( + s, + s->new_picture .data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, + s->current_picture.data[0] + s->mb_x*16 + s->mb_y*s->linesize*16, + w, h, s->linesize); + s->current_picture.error[1] += sse( + s, + s->new_picture .data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8, + s->current_picture.data[1] + s->mb_x*8 + s->mb_y*s->uvlinesize*8, + w>>1, h>>1, s->uvlinesize); + s->current_picture.error[2] += sse( + s, + s->new_picture .data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8, + s->current_picture.data[2] + s->mb_x*8 + s->mb_y*s->uvlinesize*8, + w>>1, h>>1, s->uvlinesize); + } //printf("MB %d %d bits\n", s->mb_x+s->mb_y*s->mb_width, get_bit_count(&s->pb)); } diff -r 2ac4caad5ca6 -r 8ae1e4c24e91 mpegvideo.h --- a/mpegvideo.h Wed Dec 04 12:42:25 2002 +0000 +++ b/mpegvideo.h Wed Dec 04 21:13:02 2002 +0000 @@ -48,6 +48,11 @@ #define MAX_RUN 64 #define MAX_LEVEL 64 +#define I_TYPE FF_I_TYPE // Intra +#define P_TYPE FF_P_TYPE // Predicted +#define B_TYPE FF_B_TYPE // Bi-dir predicted +#define S_TYPE FF_S_TYPE // S(GMC)-VOP MPEG4 + typedef struct Predictor{ double coeff; double count;