changeset 2613:156efe748b3d

new A-V sync correction and fps conversion stuff
author arpi
date Thu, 01 Nov 2001 21:47:28 +0000
parents 60b9c03744d3
children 9464d6f19261
files mencoder.c
diffstat 1 files changed, 45 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/mencoder.c	Thu Nov 01 21:42:37 2001 +0000
+++ b/mencoder.c	Thu Nov 01 21:47:28 2001 +0000
@@ -64,7 +64,8 @@
 static float max_pts_correction=0;//default_max_pts_correction;
 static float c_total=0;
 
-int force_fps=0;
+float force_fps=0;
+float force_ofps=0; // set to 24 for inverse telecine
 
 //#include "libmpeg2/mpeg2.h"
 //#include "libmpeg2/mpeg2_internal.h"
@@ -172,7 +173,8 @@
 
 float audio_preload=0.3;
 
-float v_timer_corr=0;
+double v_pts_corr=0;
+double v_timer_corr=0;
 
 //int out_buffer_size=0x200000;
 //unsigned char* out_buffer=malloc(out_buffer_size);
@@ -337,7 +339,7 @@
 
 mux_v->h.dwSampleSize=0; // VBR
 mux_v->h.dwScale=10000;
-mux_v->h.dwRate=mux_v->h.dwScale*sh_video->fps;
+mux_v->h.dwRate=mux_v->h.dwScale*(force_ofps?force_ofps:sh_video->fps);
 
 mux_v->codec=VCODEC_DIVX4; // 0=streamcopy
 
@@ -417,7 +419,7 @@
     // init divx4linux:
     enc_param.x_dim=sh_video->disp_w;
     enc_param.y_dim=sh_video->disp_h;
-    enc_param.framerate=sh_video->fps;
+    enc_param.framerate=(float)mux_v->h.dwRate/mux_v->h.dwScale;
     enc_param.bitrate=800000;
     enc_param.rc_period=0;
     enc_param.rc_reaction_period=0;
@@ -475,6 +477,7 @@
     float v_pts=0;
     unsigned char* start=NULL;
     int in_size;
+    int skip_flag=0; // 1=skip  -1=duplicate
 
 if(sh_audio){
     // get audio:
@@ -540,11 +543,34 @@
     in_size=video_read_frame(sh_video,&frame_time,&start,force_fps);
     if(in_size<0){ eof=1; break; }
     sh_video->timer+=frame_time;
+    
+    v_timer_corr-=frame_time-(float)mux_v->h.dwScale/mux_v->h.dwRate;
 
-//    if(!blit_frame) continue;
+// check frame duplicate/drop:
+
+if(v_timer_corr>=(float)mux_v->h.dwScale/mux_v->h.dwRate){
+    v_timer_corr-=(float)mux_v->h.dwScale/mux_v->h.dwRate;
+    ++skip_flag; // skip
+} else
+while(v_timer_corr<=-(float)mux_v->h.dwScale/mux_v->h.dwRate){
+    v_timer_corr+=(float)mux_v->h.dwScale/mux_v->h.dwRate;
+    --skip_flag; // dup
+}
 
-if(v_timer_corr<2*sh_video->frametime){
-// don't have to skip frame.
+while( (v_pts_corr<=-(float)mux_v->h.dwScale/mux_v->h.dwRate && skip_flag>0)
+ || (v_pts_corr<=-2*(float)mux_v->h.dwScale/mux_v->h.dwRate) ){
+    v_pts_corr+=(float)mux_v->h.dwScale/mux_v->h.dwRate;
+    --skip_flag; // dup
+}
+if( (v_pts_corr>=(float)mux_v->h.dwScale/mux_v->h.dwRate && skip_flag<0)
+ || (v_pts_corr>=2*(float)mux_v->h.dwScale/mux_v->h.dwRate) )
+  if(skip_flag<=0){ // we can't skip more than 1 frame now
+    v_pts_corr-=(float)mux_v->h.dwScale/mux_v->h.dwRate;
+    ++skip_flag; // skip
+  }
+
+
+if(skip_flag<=0){ // don't have to skip frame.
 switch(mux_v->codec){
 case 0:
     mux_v->buffer=start;
@@ -579,19 +605,20 @@
     aviwrite_write_chunk(muxer,mux_v,muxer_f,enc_frame.length,enc_result.is_key_frame?0x10:0);
     break;
 }
-if(v_timer_corr<-2*sh_video->frametime){
+
+if(skip_flag<0){
     // duplicate frame
-    printf("\nduplicate frame!!!    \n");
-    aviwrite_write_chunk(muxer,mux_v,muxer_f,0,0);
-    v_timer_corr+=(float)mux_v->h.dwScale/mux_v->h.dwRate;
-//    v_timer_corr=0;
+    printf("\nduplicate %d frame(s)!!!    \n",-skip_flag);
+    while(skip_flag<0){
+	aviwrite_write_chunk(muxer,mux_v,muxer_f,0,0);
+	++skip_flag;
+    }
 }
 
 } else {
     // skip frame
     printf("\nskip frame!!!    \n");
-    v_timer_corr-=(float)mux_v->h.dwScale/mux_v->h.dwRate;
-//    v_timer_corr=0;
+    --skip_flag;
 }
 
 if(sh_audio){
@@ -612,7 +639,7 @@
     }
     v_pts=d_video->pts;
     // av = compensated (with out buffering delay) A-V diff
-    AV_delay=(a_pts-v_pts); AV_delay-=mux_a->timer-(mux_v->timer-v_timer_corr);
+    AV_delay=(a_pts-v_pts); AV_delay-=mux_a->timer-(mux_v->timer-(v_timer_corr+v_pts_corr));
 	// compensate input video timer by av:
         x=AV_delay*0.1f;
         if(x<-max_pts_correction) x=-max_pts_correction; else
@@ -623,12 +650,12 @@
           max_pts_correction=sh_video->frametime*0.10; // +-10% of time
 	// sh_video->timer-=x;
 	c_total+=x;
-	v_timer_corr+=x;
+	v_pts_corr+=x;
 
-    printf("A:%6.1f V:%6.1f A-V:%7.3f oAV:%7.3f diff:%7.3f ct:%7.3f vtc:%7.3f   \r",
+    printf("A:%6.1f V:%6.1f A-V:%7.3f oAV:%7.3f diff:%7.3f ct:%7.3f vpc:%7.3f   \r",
 	a_pts,v_pts,a_pts-v_pts,
 	(float)(mux_a->timer-mux_v->timer),
-	AV_delay, c_total, v_timer_corr );
+	AV_delay, c_total, v_pts_corr );
 
 }