changeset 17659:92ac78a93625

Fix video delay when encoding with B-frames. Encoding delay is adjusted for on-the-fly during encoding. Decoding delay is compensated for by setting an appropriate dwStart on the audio stream (only in muxer_avi at this point).
author corey
date Tue, 21 Feb 2006 09:39:22 +0000
parents d407eb5bcd68
children fbff80473a6d
files libmpcodecs/ve_lavc.c libmpcodecs/ve_x264.c libmpcodecs/ve_xvid.c libmpcodecs/ve_xvid4.c libmpdemux/muxer_avi.c mencoder.c
diffstat 6 files changed, 37 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libmpcodecs/ve_lavc.c	Mon Feb 20 23:50:40 2006 +0000
+++ b/libmpcodecs/ve_lavc.c	Tue Feb 21 09:39:22 2006 +0000
@@ -770,6 +770,8 @@
         mux_v->bih->biSize= sizeof(BITMAPINFOHEADER) + lavc_venc_context->extradata_size;
     }
     
+    mux_v->decoder_delay = lavc_venc_context->max_b_frames ? 1 : 0;
+    
     return 1;
 }
 
@@ -854,8 +856,10 @@
 	out_size = avcodec_encode_video(lavc_venc_context, mux_v->buffer, mux_v->buffer_size,
 	    pic);
 
-    if(out_size == 0)
+    if(out_size == 0) {
+        ++mux_v->encoder_delay;
         return 0;
+    }
            
     muxer_write_chunk(mux_v,out_size,lavc_venc_context->coded_frame->key_frame?0x10:0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
         
--- a/libmpcodecs/ve_x264.c	Mon Feb 20 23:50:40 2006 +0000
+++ b/libmpcodecs/ve_x264.c	Tue Feb 21 09:39:22 2006 +0000
@@ -435,6 +435,11 @@
         return 0;
     }
     
+    if (mod->param.i_bframe > 1 && mod->param.b_bframe_pyramid)
+        mod->mux->decoder_delay = 2;
+    else
+        mod->mux->decoder_delay = mod->param.i_bframe ? 1 : 0;
+    
     return 1;
 }
 
@@ -511,6 +516,8 @@
                         && frame_ref == 1 && !bframe);
         muxer_write_chunk(mod->mux, i_size, keyframe?0x10:0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
     }
+    else
+        ++mod->mux->encoder_delay;
 
     return i_size;
 }
--- a/libmpcodecs/ve_xvid.c	Mon Feb 20 23:50:40 2006 +0000
+++ b/libmpcodecs/ve_xvid.c	Tue Feb 21 09:39:22 2006 +0000
@@ -378,6 +378,10 @@
 
     vbrInit(&fp->vbr_state);
 
+#ifdef XVID_API_UNSTABLE
+    fp->mux->decoder_delay = enc_param.max_bframes ? 1 : 0;
+#endif
+
     return 1;
 }
 
@@ -523,7 +527,10 @@
 #endif
     
     // write output
+    if (fp->enc_frame.length > 0)
     muxer_write_chunk(fp->mux, fp->enc_frame.length, fp->enc_frame.intra==1 ? 0x10 : 0, MP_NOPTS_VALUE, MP_NOPTS_VALUE);
+    else
+		++fp->mux->encoder_delay;
 
     // update the VBR engine
     vbrUpdate(&fp->vbr_state, enc_stats.quant, fp->enc_frame.intra,
--- a/libmpcodecs/ve_xvid4.c	Mon Feb 20 23:50:40 2006 +0000
+++ b/libmpcodecs/ve_xvid4.c	Tue Feb 21 09:39:22 2006 +0000
@@ -504,6 +504,8 @@
 	/* Store the encoder instance into the private data */
 	mod->instance = mod->create.handle;
 
+	mod->mux->decoder_delay = mod->create.max_bframes ? 1 : 0;
+
 	return(FINE);
 }
 
@@ -620,7 +622,10 @@
 	}
 
 	/* If size is == 0, we're done with that frame */
-	if(size == 0) return(FINE);
+	if(size == 0) {
+		++mod->mux->encoder_delay;
+		return(FINE);
+	}
 
 	/* xvidcore returns stats about encoded frame in an asynchronous way
 	 * accumulate these stats */
--- a/libmpdemux/muxer_avi.c	Mon Feb 20 23:50:40 2006 +0000
+++ b/libmpdemux/muxer_avi.c	Tue Feb 21 09:39:22 2006 +0000
@@ -665,10 +665,19 @@
   }
 }
 
+static void avifile_fix_parameters(muxer_stream_t *s){
+  /* adjust audio_delay_fix according to individual stream delay */
+  if (s->type == MUXER_TYPE_AUDIO)
+    s->muxer->audio_delay_fix -= (float)s->decoder_delay * s->h.dwScale/s->h.dwRate;
+  if (s->type == MUXER_TYPE_VIDEO)
+    s->muxer->audio_delay_fix += (float)s->decoder_delay * s->h.dwScale/s->h.dwRate;
+}
+
 int muxer_init_muxer_avi(muxer_t *muxer){
   muxer->cont_new_stream = &avifile_new_stream;
   muxer->cont_write_chunk = &avifile_write_chunk;
   muxer->cont_write_header = &avifile_write_header;
   muxer->cont_write_index = &avifile_write_index;
+  muxer->fix_stream_parameters = &avifile_fix_parameters;
   return 1;
 }
--- a/mencoder.c	Mon Feb 20 23:50:40 2006 +0000
+++ b/mencoder.c	Tue Feb 21 09:39:22 2006 +0000
@@ -1394,6 +1394,9 @@
     AV_delay-=audio_delay;
     AV_delay /= playback_speed;
     AV_delay-=mux_a->timer-(mux_v->timer-(v_timer_corr+v_pts_corr));
+    // adjust for encoder delays
+    AV_delay -= (float) mux_a->encoder_delay * mux_a->h.dwScale/mux_a->h.dwRate;
+    AV_delay += (float) mux_v->encoder_delay * mux_v->h.dwScale/mux_v->h.dwRate;
 	// compensate input video timer by av:
         x=AV_delay*0.1f;
         if(x<-max_pts_correction) x=-max_pts_correction; else