diff options
author | phintuka <phintuka> | 2009-08-02 11:21:22 +0000 |
---|---|---|
committer | phintuka <phintuka> | 2009-08-02 11:21:22 +0000 |
commit | 5e5c7ac783ca78c621921f7bbde1e1a55e411e51 (patch) | |
tree | 592c8c651b0d8568d287e21b206d8109b3be90a8 | |
parent | e8ca115f735b870b610d184342813064304d4352 (diff) | |
download | xineliboutput-5e5c7ac783ca78c621921f7bbde1e1a55e411e51.tar.gz xineliboutput-5e5c7ac783ca78c621921f7bbde1e1a55e411e51.tar.bz2 |
New algorithm for live mode sync of xineliboutput providing
much smoother buffer control. CVS version of live mode sync
as of 2009-06-14 was not quite sufficient for the purposes
of FRC [1].
Originally from [2] and discussed on the list [3].
Signed-off-by: Thomas Hilber <sparkie@lowbyte.de>
Signed-off-by: Paul Menzel <paulepanter@users.sourceforge.net>
[1] http://frc.easy-vdr.de/
[2] http://easy-vdr.de/git?p=frc.git/.git;a=blob;f=patches/xineliboutput-tuning-step.patch;h=9d1c56b2268125436fa3eccfebcfc3492ab204ce;hb=b9e67f4b27f1b7b1dbb2aabf3e36187e229ea63
[3] http://sourceforge.net/mailarchive/forum.php?thread_name=1248261373.14347.6032.camel%40ph-laptop&forum_name=xineliboutput-devel
-rw-r--r-- | xine_input_vdr.c | 92 |
1 files changed, 75 insertions, 17 deletions
diff --git a/xine_input_vdr.c b/xine_input_vdr.c index 468f821c..88552cb9 100644 --- a/xine_input_vdr.c +++ b/xine_input_vdr.c @@ -4,7 +4,7 @@ * See the main source file 'xineliboutput.c' for copyright information and * how to reach the author. * - * $Id: xine_input_vdr.c,v 1.278 2009-08-01 20:23:29 phintuka Exp $ + * $Id: xine_input_vdr.c,v 1.279 2009-08-02 11:21:22 phintuka Exp $ * */ @@ -124,7 +124,7 @@ # include <linux/unistd.h> /* syscall(__NR_gettid) */ #endif -static const char module_revision[] = "$Id: xine_input_vdr.c,v 1.278 2009-08-01 20:23:29 phintuka Exp $"; +static const char module_revision[] = "$Id: xine_input_vdr.c,v 1.279 2009-08-02 11:21:22 phintuka Exp $"; static const char log_module_input_vdr[] = "[input_vdr] "; #define LOG_MODULENAME log_module_input_vdr #define SysLogLevel iSysLogLevel @@ -310,12 +310,18 @@ typedef struct vdr_input_plugin_s { /* SCR */ adjustable_scr_t *scr; int speed_before_pause; - int8_t scr_tuning; + int16_t scr_tuning; uint8_t fixed_scr : 1; uint8_t scr_live_sync : 1; uint8_t is_paused : 1; uint8_t is_trickspeed : 1; - + struct { + /* buffer level data for scr tuning algorithm */ + uint cnt; + uint fill_avg; + uint fill_min; + uint fill_max; + } scr_buf; uint I_frames; /* amount of I-frames passed to demux */ uint B_frames; uint P_frames; @@ -471,10 +477,9 @@ static void mutex_cleanup(void *arg) * fine tuning is used to change playback speed in live mode * to keep in sync with mpeg source * - * SCR code is mostly copied from xine-lib (src/input/input_pvr.c) */ -#define SCR_TUNING_PAUSED -3 +#define SCR_TUNING_PAUSED -10000 #define SCR_TUNING_OFF 0 #ifdef LOG_SCR @@ -665,17 +670,68 @@ static void vdr_adjust_realtime_speed(vdr_input_plugin_t *this) else scr_tuning = SCR_TUNING_OFF; } else { - if( num_used > 4*num_free && this->class->scr_tuning_step >= 0.001) - scr_tuning = +2; /* play 1% faster */ - else if( num_used > 2*num_free ) - scr_tuning = +1; /* play .5% faster */ - else if( num_free > 4*num_used && this->class->scr_tuning_step >= 0.001) /* <20% */ - scr_tuning = -2; /* play 1% slower */ - else if( num_free > 2*num_used ) /* <33% */ - scr_tuning = -1; /* play .5% slower */ - else if( (scr_tuning > 0 && num_free > num_used) || - (scr_tuning < 0 && num_used > num_free) ) - scr_tuning = SCR_TUNING_OFF; + + /* + * Experimental only. + * Major sync point displacements are handled by xine-lib. + * This provides much faster sync after channel switch, replay start etc. + */ + + int bfill, trim_rel, trim_act; + + #define DIVIDER 8000 + #define WEIGHTING 2 + #define CENTER_POS 0 + #define MAX_TRIM_REL 1 + #define MAX_TRIM_ABS 2 + #define MIN_FILL_PER_CENT 0 + #define MAX_FILL_PER_CENT 100 + #define TARGET_FILL_PER_CENT 50 + +#ifdef LOG_GRAPH + if (!this->scr_buf.cnt) { + log_graph(0, 0); + printf(" R\n"); + } +#endif + trim_act = scr_tuning - CENTER_POS; + bfill = MAX_FILL_PER_CENT * num_used / (num_used + num_free); + this->scr_buf.fill_avg += bfill; + this->scr_buf.fill_min = MIN(this->scr_buf.fill_min, bfill); + this->scr_buf.fill_max = MAX(this->scr_buf.fill_max, bfill); + +#ifdef LOG_GRAPH + log_graph(bfill, '.'); +#endif + ++this->scr_buf.cnt; + if (!(this->scr_buf.cnt % DIVIDER)) { + this->scr_buf.fill_avg /= DIVIDER; + trim_rel = (this->scr_buf.fill_avg - TARGET_FILL_PER_CENT) / WEIGHTING; + trim_rel = MIN(trim_rel, MAX_TRIM_REL); + trim_rel = MAX(trim_rel, -MAX_TRIM_REL); + +#ifdef LOG_GRAPH + log_graph(this->scr_buf.fill_avg, '|'); + log_graph(0, 1); + printf(" %2d%% %2d%% %2d%% [%3d%+4d]\n", + this->scr_buf.fill_min, + this->scr_buf.fill_max, + this->scr_buf.fill_avg, + trim_act, trim_rel); +#endif + + this->scr_buf.fill_avg = 0; + this->scr_buf.fill_min = MAX_FILL_PER_CENT; + this->scr_buf.fill_max = MIN_FILL_PER_CENT; + + if (trim_rel) { + trim_act += trim_rel; + trim_act = MIN(trim_act, MAX_TRIM_ABS); + trim_act = MAX(trim_act, -MAX_TRIM_ABS); + /* reprog clock correction */ + scr_tuning = trim_act + CENTER_POS; + } + } } if( scr_tuning != this->scr_tuning ) { @@ -4390,6 +4446,8 @@ static buf_element_t *preprocess_buf(vdr_input_plugin_t *this, buf_element_t *bu pthread_mutex_lock (&this->stream->first_frame_lock); this->stream->first_frame_flag = 2; pthread_mutex_unlock (&this->stream->first_frame_lock); + + memset(&this->scr_buf, 0, sizeof(this->scr_buf)); } pthread_mutex_unlock(&this->lock); |