summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorsten Jager <t.jager@gmx.de>2013-12-18 11:39:35 +0100
committerTorsten Jager <t.jager@gmx.de>2013-12-18 11:39:35 +0100
commit95c27f0232bf3dd707c4b03a5be4319cfb205d01 (patch)
tree99f4c50399dd4455ab45249c79ab6ca1eab5a983
parent4c4626617218d7df73677ba4c0869f9a0c54378d (diff)
downloadxine-lib-95c27f0232bf3dd707c4b03a5be4319cfb205d01.tar.gz
xine-lib-95c27f0232bf3dd707c4b03a5be4319cfb205d01.tar.bz2
Fix metronom video drift compensation.
Old code was broken in 2 ways: * It repeatedly multiplied drift by 29/30, thus never reaching 0. * If decoder does not always set vo_frame.duration, strange jumps appeared.
-rw-r--r--src/xine-engine/metronom.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index cdadf11f4..1baa73f84 100644
--- a/src/xine-engine/metronom.c
+++ b/src/xine-engine/metronom.c
@@ -481,41 +481,62 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
this->force_video_jump = 0;
this->video_vpts = vpts;
this->video_drift = 0;
+ this->video_drift_step = 0;
- xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video jump\n");
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "metronom: video jump by %"PRId64" pts\n", diff);
} else {
-
- this->video_drift = diff;
- this->video_drift_step = diff / 30;
- /* this will fix video drift with a constant compensation each
- frame for about 1 second of video. */
-
- if (diff) lprintf("video drift, drift is %" PRId64 "\n", this->video_drift);
+ /* TJ. Drift into new value over the next 30 frames.
+ Dont fall into the asymptote trap of bringing down step with remaining drift. */
+ int64_t step;
+ if (diff < 0) {
+ step = (diff - 29) / 30;
+ if (this->video_drift_step < step)
+ step = this->video_drift_step < diff ? diff : this->video_drift_step;
+ } else {
+ step = (diff + 29) / 30;
+ if (this->video_drift_step > step)
+ step = this->video_drift_step > diff ? diff : this->video_drift_step;
+ }
+ this->video_drift = diff;
+ this->video_drift_step = step;
}
} else {
/* VIDEO_PTS_MODE: do not use the predicted value */
- this->video_vpts = vpts;
+ this->video_drift = 0;
+ this->video_drift_step = 0;
+ this->video_vpts = vpts;
}
}
img->vpts = this->video_vpts + this->av_offset;
+ /* We need to update this->video_vpts is both modes.
+ * this->video_vpts is used as the next frame vpts if next frame pts=0
+ */
+ this->video_vpts += this->img_duration - this->video_drift_step;
+
if (this->video_mode == VIDEO_PREDICTION_MODE) {
lprintf("video vpts for %10"PRId64" : %10"PRId64" (duration:%d drift:%" PRId64 " step:%" PRId64 ")\n",
pts, this->video_vpts, img->duration, this->video_drift, this->video_drift_step );
- if (this->video_drift * this->video_drift_step > 0) {
- img->duration -= this->video_drift_step;
- this->img_duration = img->duration;
+ /* reset drift compensation if work is done after this frame */
+ if (this->video_drift_step) {
this->video_drift -= this->video_drift_step;
+ if (this->video_drift_step < 0) {
+ if (this->video_drift >= 0) {
+ this->video_drift = 0;
+ this->video_drift_step = 0;
+ }
+ } else {
+ if (this->video_drift <= 0) {
+ this->video_drift = 0;
+ this->video_drift_step = 0;
+ }
+ }
}
}
- /* We need to update this->video_vpts is both modes.
- * this->video_vpts is used as the next frame vpts if next frame pts=0
- */
- this->video_vpts += this->img_duration;
if (this->master) {
this->master->set_option(this->master, METRONOM_LOCK, 0);