summaryrefslogtreecommitdiff
path: root/src/xine-engine/metronom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine/metronom.c')
-rw-r--r--src/xine-engine/metronom.c88
1 files changed, 50 insertions, 38 deletions
diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c
index f1803e431..57c34698b 100644
--- a/src/xine-engine/metronom.c
+++ b/src/xine-engine/metronom.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: metronom.c,v 1.137 2004/04/09 15:06:02 mroi Exp $
+ * $Id: metronom.c,v 1.138 2004/04/22 23:19:03 tmattern Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -39,7 +39,6 @@
#define LOG
#define LOG_AUDIO
*/
-
#define METRONOM_INTERNAL
#define METRONOM_CLOCK_INTERNAL
@@ -55,6 +54,10 @@
#define VIDEO_DRIFT_TOLERANCE 45000
#define AUDIO_DRIFT_TOLERANCE 45000
+/* metronom video modes */
+#define VIDEO_PREDICTION_MODE 0 /* use pts + frame duration */
+#define VIDEO_PTS_MODE 1 /* use only pts */
+
/* redefine abs as macro to handle 64-bit diffs.
i guess llabs may not be available everywhere */
#define abs(x) ( ((x)<0) ? -(x) : (x) )
@@ -456,20 +459,25 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
this->img_cpt++;
+ if (img->duration) {
+ this->video_mode = VIDEO_PREDICTION_MODE;
+ this->img_duration = img->duration;
+ } else {
+ /* will skip the whole predicted vpts stuff */
+ this->video_mode = VIDEO_PTS_MODE;
+ }
+
if (pts && pts != this->last_video_pts) {
- /*
- * Compute img duration if it's not provided by the decoder
- * example: mpeg streams with an invalid frame rate
- */
if (!img->duration) {
+ /* Compute the duration of previous frames using this formula:
+ * duration = (curent_pts - last_pts) / (frame count between the 2 pts)
+ * This duration will be used to predict the next frame vpts.
+ */
if (this->last_video_pts && this->img_cpt) {
this->img_duration = (pts - this->last_video_pts) / this->img_cpt;
lprintf("computed frame_duration = %" PRId64 "\n", this->img_duration );
}
- img->duration = this->img_duration;
- } else {
- this->img_duration = img->duration;
}
this->img_cpt = 0;
this->last_video_pts = pts;
@@ -484,49 +492,53 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) {
vpts = pts + this->vpts_offset;
- diff = this->video_vpts - vpts;
-
- lprintf("video diff is %" PRId64 " (predicted %" PRId64 ", given %" PRId64 ")\n", diff, this->video_vpts, vpts);
+ if (this->video_mode == VIDEO_PREDICTION_MODE) {
+
+ diff = this->video_vpts - vpts;
- if ((abs (diff) > VIDEO_DRIFT_TOLERANCE) || (this->force_video_jump)) {
- this->force_video_jump = 0;
- this->video_vpts = vpts;
- this->video_drift = 0;
+ lprintf("video diff is %" PRId64 " (predicted %" PRId64 ", given %" PRId64 ")\n", diff, this->video_vpts, vpts);
- xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video jump\n");
- } else {
+ if ((abs (diff) > VIDEO_DRIFT_TOLERANCE) || (this->force_video_jump)) {
+ this->force_video_jump = 0;
+ this->video_vpts = vpts;
+ this->video_drift = 0;
- 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. */
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video jump\n");
- if (diff) lprintf("video drift, drift is %" PRId64 "\n", this->video_drift);
- }
- } else {
- if (!img->duration) {
- img->duration = this->img_duration;
+ } 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);
+ }
} else {
- this->img_duration = img->duration;
+ /* VIDEO_PTS_MODE: do not use the predicted value */
+ this->video_vpts = vpts;
}
}
-
img->vpts = this->video_vpts + this->av_offset;
- lprintf("video vpts for %10lld : %10lld (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;
+ if (this->video_mode == VIDEO_PREDICTION_MODE) {
+ lprintf("video vpts for %10lld : %10lld (duration:%d drift:%" PRId64 " step:%" PRId64 ")\n",
+ pts, this->video_vpts, img->duration, this->video_drift, this->video_drift_step );
- 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;
+ this->video_drift -= this->video_drift_step;
+ }
}
-
- this->video_vpts += img->duration;
+ /* 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;
+
pthread_mutex_unlock (&this->lock);
}