summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorphintuka <phintuka>2009-08-02 11:21:22 +0000
committerphintuka <phintuka>2009-08-02 11:21:22 +0000
commit5e5c7ac783ca78c621921f7bbde1e1a55e411e51 (patch)
tree592c8c651b0d8568d287e21b206d8109b3be90a8
parente8ca115f735b870b610d184342813064304d4352 (diff)
downloadxineliboutput-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.c92
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);