From 0d1e924668b1384ffbf4282e077f262a2c538596 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 6 Dec 2002 13:30:13 +0000 Subject: [PATCH] fixing 2pass assert failure better dynamic b frame selection, still not very good though allthough it works fine without 2pass now Originally committed as revision 1316 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/mpegvideo.c | 131 ++++++++++++++++++++++++++++----------- libavcodec/mpegvideo.h | 3 +- libavcodec/ratecontrol.c | 33 +--------- 3 files changed, 97 insertions(+), 70 deletions(-) diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index c1a0b0b55c..63338012ff 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -780,7 +780,6 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx) /* mark&release old frames */ if (s->pict_type != B_TYPE && s->last_picture.data[0]) { - Picture *pic= NULL; for(i=0; ipicture[i].data[0] == s->last_picture.data[0]){ // s->picture[i].reference=0; @@ -898,6 +897,39 @@ void MPV_frame_end(MpegEncContext *s) } } +static int get_sae(uint8_t *src, int ref, int stride){ + int x,y; + int acc=0; + + for(y=0; y<16; y++){ + for(x=0; x<16; x++){ + acc+= ABS(src[x+y*stride] - ref); + } + } + + return acc; +} + +static int get_intra_count(MpegEncContext *s, uint8_t *src, uint8_t *ref, int stride){ + int x, y, w, h; + int acc=0; + + w= s->width &~15; + h= s->height&~15; + + for(y=0; ydsp.pix_abs16x16(src + offset, ref + offset, stride); + int mean= (s->dsp.pix_sum(src + offset, stride) + 128)>>8; + int sae = get_sae(src + offset, mean, stride); + + acc+= sae + 500 < sad; + } + } + return acc; +} + static int load_input_picture(MpegEncContext *s, AVVideoFrame *pic_arg){ AVVideoFrame *pic; int i,r; @@ -991,50 +1023,75 @@ static void select_input_picture(MpegEncContext *s){ /* set next picture types & ordering */ if(s->reordered_input_picture[0]==NULL && s->input_picture[0]){ - 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; - + 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; + }else{ + int b_frames; + + if(s->flags&CODEC_FLAG_PASS2){ + for(i=0; imax_b_frames+1; i++){ + int pict_num= s->input_picture[0]->display_picture_number + i; + int pict_type= s->rc_context.entry[pict_num].new_pict_type; + s->input_picture[i]->pict_type= pict_type; + + if(i + 1 >= s->rc_context.num_entries) break; + } + } + + if(s->input_picture[0]->pict_type){ + /* user selected pict_type */ 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{ - 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; - }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; + }else if(s->b_frame_strategy==0){ + b_frames= s->max_b_frames; + }else if(s->b_frame_strategy==1){ + for(i=1; imax_b_frames+1; i++){ + if(s->input_picture[i]->b_frame_score==0){ + s->input_picture[i]->b_frame_score= + get_intra_count(s, s->input_picture[i ]->data[0] + 16, + s->input_picture[i-1]->data[0] + 16, s->linesize) + 1; + } + } 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; - } + if(s->input_picture[i]->b_frame_score - 1 > s->mb_num/40) break; + } + + b_frames= FFMAX(0, i-1); + + /* reset scores */ + for(i=0; iinput_picture[i]->b_frame_score=0; + } + }else{ + fprintf(stderr, "illegal b frame strategy\n"); + b_frames=0; + } + + emms_c(); +//static int b_count=0; +//b_count+= b_frames; +//printf("b_frames: %d\n", b_count); + + s->reordered_input_picture[0]= s->input_picture[b_frames]; + if( s->picture_in_gop_number + b_frames >= s->gop_size + || s->reordered_input_picture[0]->pict_type== I_TYPE) + 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; ireordered_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; } } } diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 46e19d4b17..fad4f8eaf1 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -38,7 +38,7 @@ enum OutputFormat { #define MAX_FCODE 7 #define MAX_MV 2048 -#define MAX_PICTURE_COUNT 7 +#define MAX_PICTURE_COUNT 15 #define ME_MAP_SIZE 64 #define ME_MAP_SHIFT 3 @@ -117,6 +117,7 @@ typedef struct Picture{ uint16_t *mb_var; /* Table for MB variances */ uint16_t *mc_mb_var; /* Table for motion compensated MB variances */ uint8_t *mb_mean; /* Table for MB luminance */ + int b_frame_score; /* */ } Picture; typedef struct ParseContext{ diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index caea09b24b..e4f2340c74 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -714,38 +714,7 @@ static int init_pass2(MpegEncContext *s) for(i=0; inum_entries; i++){ RateControlEntry *rce= &rcc->entry[i]; - if(s->b_frame_strategy==0 || s->max_b_frames==0){ - rce->new_pict_type= rce->pict_type; - }else{ - int j; - int next_non_b_type=P_TYPE; - - switch(rce->pict_type){ - case I_TYPE: - if(i-last_i_frame>s->gop_size/2){ //FIXME this is not optimal - rce->new_pict_type= I_TYPE; - last_i_frame= i; - }else{ - rce->new_pict_type= P_TYPE; // will be caught by the scene detection anyway - } - break; - case P_TYPE: - rce->new_pict_type= P_TYPE; - break; - case B_TYPE: - for(j=i+1; jmax_b_frames+2 && jnum_entries; j++){ - if(rcc->entry[j].pict_type != B_TYPE){ - next_non_b_type= rcc->entry[j].pict_type; - break; - } - } - if(next_non_b_type==I_TYPE) - rce->new_pict_type= P_TYPE; - else - rce->new_pict_type= B_TYPE; - break; - } - } + rce->new_pict_type= rce->pict_type; rcc->i_cplx_sum [rce->pict_type] += rce->i_tex_bits*rce->qscale; rcc->p_cplx_sum [rce->pict_type] += rce->p_tex_bits*rce->qscale; rcc->mv_bits_sum[rce->pict_type] += rce->mv_bits;