[MPlayer-dev-eng] Re: [patch] A-V sync tuneup, round 2
PALLAI Roland
dap at omnis.hu
Wed Nov 7 21:17:06 CET 2001
> your patch has lines with no if(use_dap_sync) before. for example
> resetting relative timer. it will break timing code.
ah, fixed
> i prefer well commented (english! :)) patches.
I've renamed some variables, I hope it's easier to understand, now ;}
>> note3: RPC timer should be used for timing based on 8khz clock.
>> note4: RPC is usually disabled for 'average' users. and HZ=100.
> hm, I didn't think on it, cause I had never enabled it. :} it's a Good
> Thing, I'll test it tomorrow.. but softsleep even required by
> non-linux platforms and RPC-less users
bad news: only the root can use it, users can't, because they can't
enable interrupts.. it's now implemented, but works only for root
--
DaP
-------------- next part --------------
diff -urN -x configure -x config.h.in -x aclocal.m4 -x *~ -x *.P -x stamp-h -x stamp-h.in -x config.cache -x config.log -x config.status -x config.h -x Makefile -x POTFILES -x .depend -x config.mak -x version.h -x mplayer.txt -x .#* -x CVS -x loader main/cfg-mplayer.h main-dev/cfg-mplayer.h
--- main/cfg-mplayer.h Tue Oct 23 22:15:00 2001
+++ main-dev/cfg-mplayer.h Sat Nov 3 15:37:37 2001
@@ -290,5 +290,6 @@
{"-help", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
{"help", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
{"h", help_text, CONF_TYPE_PRINT, CONF_NOCFG, 0, 0},
+ {"nodapsync", &nodapsync, CONF_TYPE_FLAG, 0, 0, 1},
{NULL, NULL, 0, 0, 0, 0}
};
diff -urN -x configure -x config.h.in -x aclocal.m4 -x *~ -x *.P -x stamp-h -x stamp-h.in -x config.cache -x config.log -x config.status -x config.h -x Makefile -x POTFILES -x .depend -x config.mak -x version.h -x mplayer.txt -x .#* -x CVS -x loader main/mplayer.c main-dev/mplayer.c
--- main/mplayer.c Mon Oct 29 00:38:52 2001
+++ main-dev/mplayer.c Wed Nov 7 20:31:24 2001
@@ -69,6 +69,10 @@
#include "Gui/mplayer/play.h"
#endif
+#ifdef TARGET_LINUX
+#include <linux/rtc.h>
+#endif
+
#define DEBUG if(0)
int verbose=0;
int quiet=0;
@@ -79,6 +83,8 @@
void find_sub(subtitle* subtitles,int key);
#endif
+int nodapsync = 0;
+
//**************************************************************************//
// Config file
//**************************************************************************//
@@ -1126,12 +1132,16 @@
char osd_text_buffer[64];
int drop_frame=0;
int drop_frame_cnt=0;
+int too_slow_frame_cnt=0;
+int too_fast_frame_cnt=0;
// for auto-quality:
float AV_delay=0; // average of A-V timestamp differences
double cvideo_base_vtime;
double cvideo_base_vframe;
double vdecode_time;
-
+unsigned int lastframeout_ts;
+float time_frame_corr_avg=0;
+int rtc_fd=-1;
//================ SETUP AUDIO ==========================
current_module="setup_audio";
@@ -1192,6 +1202,34 @@
//==================== START PLAYING =======================
+if (!nodapsync) {
+#ifdef TARGET_LINUX
+ if ((rtc_fd = open("/dev/rtc", O_RDONLY)) < 0)
+ perror ("Linux RTC init: open");
+ else {
+ unsigned long irqp;
+
+ /* if (ioctl(rtc_fd, RTC_IRQP_SET, _) < 0) { */
+ if (ioctl(rtc_fd, RTC_IRQP_READ, &irqp) < 0) {
+ perror ("Linux RTC init: ioctl (rtc_irqp_read)");
+ close (rtc_fd);
+ rtc_fd = -1;
+ } else if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) {
+ /* variable only by the root */
+ perror ("Linux RTC init: ioctl (rtc_pie_on)");
+ close (rtc_fd);
+ rtc_fd = -1;
+ }
+ if (rtc_fd > 0)
+ printf ("Using Linux's hardware RTC timing (%ldHz)\n", irqp);
+ else
+#endif
+ printf ("Using software timing\n");
+#ifdef TARGET_LINUX
+ }
+#endif
+}
+
mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_StartPlaying);fflush(stdout);
if(!use_stdin){
@@ -1367,7 +1405,7 @@
// Increase video timers:
sh_video->num_frames+=frame_time;
++sh_video->num_frames_decoded;
- frame_time*=sh_video->frametime;
+ frame_time*=sh_video->frametime; /* CHECKME: if mpeg2 { ft != 1 } */
if(demuxer->file_format==DEMUXER_TYPE_ASF && !force_fps){
// .ASF files has no fixed FPS - just frame durations!
float d=d_video->pts-pts1;
@@ -1418,29 +1456,71 @@
// It's time to sleep...
current_module="sleep";
- time_frame-=GetRelativeTime(); // reset timer
+ time_frame-=GetRelativeTime(); // reset timer -- for nosound
if(sh_audio && !d_audio->eof){
int delay=audio_out->get_delay();
mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"delay=%d\n",delay);
- time_frame=sh_video->timer;
- time_frame-=sh_audio->timer-(float)delay/(float)sh_audio->o_bps;
- // we are out of time... drop next frame!
- if(time_frame<-2*frame_time){
- static int drop_message=0;
- drop_frame=frame_dropping; // tricky!
- ++drop_frame_cnt;
- if(drop_frame_cnt>50 && AV_delay>0.5 && !drop_message){
- drop_message=1;
- mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
- }
- mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nframe drop %d, %.2f\n", drop_frame, time_frame);
- }
- } else {
- if( (time_frame<-3*frame_time || time_frame>3*frame_time) || benchmark)
- time_frame=0;
-
- }
+ if (nodapsync) {
+ /* Arpi's AV-sync */
+ time_frame=sh_video->timer;
+ time_frame-=sh_audio->timer-(float)delay/(float)sh_audio->o_bps;
+ if (time_frame < -2 * frame_time) {
+ static int drop_message=0;
+ drop_frame=frame_dropping; // tricky!
+ ++drop_frame_cnt;
+ if(drop_frame_cnt>50 && AV_delay>0.5 && !drop_message){
+ drop_message=1;
+ mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
+ }
+ printf ("WARNING (nodapsync): A-V SYNC FAILED: FRAMEDROP!\n");
+ mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nframe drop %d, %.2f\n", drop_frame, time_frame);
+ } else {
+ if( (time_frame<-3*frame_time || time_frame>3*frame_time) || benchmark)
+ time_frame=0;
+ }
+ } else {
+ /* DaP's AV-sync */
+ float SH_AV_delay;
+ /* SH_AV_delay = sh_video->timer - (sh_audio->timer - (float)((float)delay + sh_audio->a_buffer_len) / (float)sh_audio->o_bps); */
+ SH_AV_delay = sh_video->timer - (sh_audio->timer - (float)((float)delay) / (float)sh_audio->o_bps);
+ // printf ("audio slp req: %.3f TF: %.3f delta: %.3f (v: %.3f a: %.3f) | ", i, time_frame,
+ // i - time_frame, sh_video->timer, sh_audio->timer - (float)((float)delay / (float)sh_audio->o_bps));
+ if(SH_AV_delay<-2*frame_time){
+ static int drop_message=0;
+ drop_frame=frame_dropping; // tricky!
+ ++drop_frame_cnt;
+ if(drop_frame_cnt>50 && AV_delay>0.5 && !drop_message){
+ drop_message=1;
+ mp_msg(MSGT_AVSYNC,MSGL_WARN,MSGTR_SystemTooSlow);
+ }
+ printf ("A-V SYNC: FRAMEDROP (SH_AV_delay=%.3f)!\n", SH_AV_delay);
+ mp_msg(MSGT_AVSYNC,MSGL_DBG2,"\nframe drop %d, %.2f\n", drop_frame, time_frame);
+ /* go into unlimited-TF cycle */
+ time_frame = SH_AV_delay;
+ } else {
+#define SL_CORR_AVG_LEN 125
+ /* don't adjust under framedropping */
+ time_frame_corr_avg = (time_frame_corr_avg * (SL_CORR_AVG_LEN - 1) +
+ (SH_AV_delay - time_frame)) / SL_CORR_AVG_LEN;
+#define UNEXP_CORR_MAX 0.1 /* limit of unexpected correction between two frames (percentage) */
+#define UNEXP_CORR_WARN 1.0 /* warn limit of A-V lag (percentage) */
+ time_frame += time_frame_corr_avg;
+ // printf ("{%.3f - %.3f}\n", i - time_frame, frame_time + frame_time_corr_avg);
+ if (SH_AV_delay - time_frame < (frame_time + time_frame_corr_avg) * UNEXP_CORR_MAX &&
+ SH_AV_delay - time_frame > (frame_time + time_frame_corr_avg) * -UNEXP_CORR_MAX)
+ time_frame = SH_AV_delay;
+ else {
+ if (SH_AV_delay - time_frame > (frame_time + time_frame_corr_avg) * UNEXP_CORR_WARN ||
+ SH_AV_delay - time_frame < (frame_time + time_frame_corr_avg) * -UNEXP_CORR_WARN)
+ printf ("WARNING: A-V SYNC LAG TOO LARGE: %.3f {%.3f - %.3f} (too little UNEXP_CORR_MAX?)\n",
+ SH_AV_delay - time_frame, SH_AV_delay, time_frame);
+ time_frame += (frame_time + time_frame_corr_avg) * ((SH_AV_delay > time_frame) ?
+ UNEXP_CORR_MAX : -UNEXP_CORR_MAX);
+ }
+ } /* /start dropframe */
+ } /* /sh_audio */
+ } /* /end dropframe */
// if(verbose>1)printf("sleep: %5.3f a:%6.3f v:%6.3f \n",time_frame,sh_audio->timer,sh_video->timer);
@@ -1451,28 +1531,77 @@
EventHandling();
}
#endif
-
- while(time_frame>0.005){
- if(time_frame<=0.020)
-// usec_sleep(10000); // sleeps 1 clock tick (10ms)!
- usec_sleep(0); // sleeps 1 clock tick (10ms)!
- else
- usec_sleep(1000000*(time_frame-0.002));
+
+#define SL_MAX_LAG 0.003 /* maximum sleep latency (ms) */
+ if (nodapsync) {
+#if 0 /* soft-sleep */
+ while(time_frame>0.000){
+ if (!(time_frame < 0.010 - SL_MAX_LAG))
+ usec_sleep(0); /* man nanosleep (2001) */
+#else
+ while(time_frame>0.005){
+ if(time_frame<=0.010)
+ usec_sleep(0); // sleeps 1 clock tick (10ms)!
+ else
+ usec_sleep(1000000*(time_frame-0.002));
+#endif
#ifdef HAVE_NEW_GUI
- if(use_gui){
- EventHandling();
- }
+ if(use_gui){
+ EventHandling();
+ }
#endif
- time_frame-=GetRelativeTime();
- }
+ time_frame-=GetRelativeTime();
+ }
+ } else {
+ int i = 0;
+
+ if (!drop_frame && time_frame < -SL_MAX_LAG) {
+ printf ("WARNING: frame decoding was too slow - no sleep (%.3f)!\n", time_frame);
+ i++;
+ }
+ while (time_frame > 0.000) {
+ unsigned long long rtc_ts;
+//printf ("TF1: %.3f\n", time_frame);
+ if (rtc_fd > 0) {
+ if (read (rtc_fd, &rtc_ts, sizeof rtc_ts) <= 0)
+ perror ("read (rtc_fd)");
+ } else
+#if 1 /* soft-sleep */
+ if (time_frame > 0.010 - SL_MAX_LAG)
+#endif
+ usec_sleep(0); /* man nanosleep (2001) */
+#ifdef HAVE_NEW_GUI
+ if(use_gui){
+ EventHandling();
+ }
+#endif
+ time_frame-=GetRelativeTime();
+//printf ("TF2: %.3f\n", time_frame);
+ }
+ if (!drop_frame && time_frame < -SL_MAX_LAG) {
+ if (!i)
+ printf ("NOTICE: too long sleep: %.3f\n", time_frame);
+ time_frame = -SL_MAX_LAG; /* may cause too_slow_cnt++ */
+ }
+ } /* /nodapsync */
current_module="flip_page";
#ifdef USE_LIBVO2
if(blit_frame) vo2_flip(video_out,0);
#else
video_out->check_events();
- if(blit_frame){
+ if(blit_frame){ /* doesn't run under framedrop */
unsigned int t2=GetTimer();
+ float j;
+#define FRAME_LAG_WARN 0.2
+ j = ((float)t2 - lastframeout_ts) / 1000000;
+ lastframeout_ts = GetTimer();
+ if (j < frame_time + frame_time * -FRAME_LAG_WARN)
+ too_fast_frame_cnt++;
+ /* printf ("PANIC: too fast frame (%.3f)!\n", j); */
+ else if (j > frame_time + frame_time * FRAME_LAG_WARN)
+ too_slow_frame_cnt++;
+ /* printf ("PANIC: too slow frame (%.3f)!\n", j); */
video_out->flip_page();
t2=GetTimer()-t2;vout_time_usage+=t2*0.000001f;
}
@@ -1541,16 +1670,21 @@
max_pts_correction=default_max_pts_correction;
else
max_pts_correction=sh_video->frametime*0.10; // +-10% of time
- sh_audio->timer+=x; c_total+=x;
- if(!quiet) mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f %3d/%3d %2d%% %2d%% %4.1f%% %d %d %d%%\r",
- a_pts-audio_delay-delay,v_pts,AV_delay,c_total,
- (int)sh_video->num_frames,(int)sh_video->num_frames_decoded,
- (sh_video->timer>0.5)?(int)(100.0*video_time_usage/(double)sh_video->timer):0,
- (sh_video->timer>0.5)?(int)(100.0*vout_time_usage/(double)sh_video->timer):0,
- (sh_video->timer>0.5)?(100.0*audio_time_usage/(double)sh_video->timer):0
+ sh_audio->timer+=x;
+ c_total+=x;
+ if(!quiet) mp_msg(MSGT_AVSYNC,MSGL_STATUS,"A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f %3d %2d%% %2d%% %4.1f%% %d %d%% [%d|%d<>%d]\r",
+ a_pts-audio_delay-delay,v_pts,AV_delay,c_total
+ ,(int)sh_video->num_frames
+// ,(int)sh_video->num_frames_decoded
+ ,(sh_video->timer>0.5)?(int)(100.0*video_time_usage/(double)sh_video->timer):0
+ ,(sh_video->timer>0.5)?(int)(100.0*vout_time_usage/(double)sh_video->timer):0
+ ,(sh_video->timer>0.5)?(100.0*audio_time_usage/(double)sh_video->timer):0
+ ,output_quality
+ ,cache_fill_status
+// ,time_frame_corr_avg
,drop_frame_cnt
- ,output_quality
- ,cache_fill_status
+ ,too_slow_frame_cnt
+ ,too_fast_frame_cnt
);
fflush(stdout);
}
@@ -1648,6 +1782,8 @@
if(use_stdin) usec_sleep(1000); // do not eat the CPU
}
osd_function=OSD_PLAY;
+ if (!nodapsync)
+ (void)GetRelativeTime(); // keep TF around FT in next cycle
if (audio_out && sh_audio)
audio_out->resume(); // resume audio
#ifdef HAVE_NEW_GUI
@@ -1916,6 +2052,8 @@
osd_visible=sh_video->fps; // to rewert to PLAY pointer after 1 sec
audio_time_usage=0; video_time_usage=0; vout_time_usage=0;
drop_frame_cnt=0;
+ too_slow_frame_cnt=0;
+ too_fast_frame_cnt=0;
}
rel_seek_secs=0;
More information about the MPlayer-dev-eng
mailing list