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
This commit is contained in:
Michael Niedermayer 2002-12-06 13:30:13 +00:00
parent 32db2b1d47
commit 0d1e924668
3 changed files with 97 additions and 70 deletions

View File

@ -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; i<MAX_PICTURE_COUNT; i++){
if(s->picture[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; y<h; y+=16){
for(x=0; x<w; x+=16){
int offset= x + y*stride;
int sad = s->dsp.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; i<s->max_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_frames<s->max_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; i<b_frames; i++){
coded_pic_num++;
s->reordered_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; i<s->max_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; i<s->max_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; i<b_frames+1; i++){
s->input_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; i<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;
}
}
}

View File

@ -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{

View File

@ -714,38 +714,7 @@ static int init_pass2(MpegEncContext *s)
for(i=0; i<rcc->num_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; j<i+s->max_b_frames+2 && j<rcc->num_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;