summaryrefslogtreecommitdiff
path: root/include/xine/metronom.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/xine/metronom.h')
-rw-r--r--include/xine/metronom.h359
1 files changed, 359 insertions, 0 deletions
diff --git a/include/xine/metronom.h b/include/xine/metronom.h
new file mode 100644
index 000000000..4f4bb04eb
--- /dev/null
+++ b/include/xine/metronom.h
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2000-2004 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * metronom: general pts => virtual calculation/assoc
+ *
+ * virtual pts: unit 1/90000 sec, always increasing
+ * can be used for synchronization
+ * video/audio frame with same pts also have same vpts
+ * but pts is likely to differ from vpts
+ *
+ * the basic idea is:
+ * video_pts + video_wrap_offset = video_vpts
+ * audio_pts + audio_wrap_offset = audio_vpts
+ *
+ * - video_wrap_offset should be equal to audio_wrap_offset as to have
+ * perfect audio and video sync. They will differ on brief periods due
+ * discontinuity correction.
+ * - metronom should also interpolate vpts values most of the time as
+ * video_pts and audio_vpts are not given for every frame.
+ * - corrections to the frame rate may be needed to cope with bad
+ * encoded streams.
+ */
+
+#ifndef HAVE_METRONOM_H
+#define HAVE_METRONOM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <pthread.h>
+
+#include <xine/video_out.h>
+#include <xine.h>
+
+typedef struct metronom_s metronom_t ;
+typedef struct metronom_clock_s metronom_clock_t;
+typedef struct scr_plugin_s scr_plugin_t;
+
+/* metronom prebuffer can be adjusted with XINE_PARAM_METRONOM_PREBUFFER.
+ * it sets how much the first video/audio frame should be delayed to
+ * have some prebuffering at the output layers. reducing this value (about
+ * 1/8 sec) may result in faster seeking (good to simulate play backwards,
+ * for example).
+ */
+#define PREBUFFER_PTS_OFFSET 12000
+
+ /* see below */
+#define DISC_STREAMSTART 0
+#define DISC_RELATIVE 1
+#define DISC_ABSOLUTE 2
+#define DISC_STREAMSEEK 3
+
+struct metronom_s {
+
+ /*
+ * called by audio output driver to inform metronom about current audio
+ * samplerate
+ *
+ * parameter pts_per_smpls : 1/90000 sec per 65536 samples
+ */
+ void (*set_audio_rate) (metronom_t *self, int64_t pts_per_smpls);
+
+ /*
+ * called by video output driver for *every* frame
+ *
+ * parameter frame containing pts, scr, ... information
+ *
+ * will set vpts field in frame
+ *
+ * this function will also update video_wrap_offset if a discontinuity
+ * is detected (read the comentaries below about discontinuities).
+ *
+ */
+
+ void (*got_video_frame) (metronom_t *self, vo_frame_t *frame);
+
+ /*
+ * called by audio output driver whenever audio samples are delivered to it
+ *
+ * parameter pts : pts for audio data if known, 0 otherwise
+ * nsamples : number of samples delivered
+ *
+ * return value: virtual pts for audio data
+ *
+ * this function will also update audio_wrap_offset if a discontinuity
+ * is detected (read the comentaries below about discontinuities).
+ *
+ */
+
+ int64_t (*got_audio_samples) (metronom_t *self, int64_t pts,
+ int nsamples);
+
+ /*
+ * called by SPU decoder whenever a packet is delivered to it
+ *
+ * parameter pts : pts for SPU packet if known, 0 otherwise
+ *
+ * return value: virtual pts for SPU packet
+ * (this is the only pts to vpts function that cannot update the wrap_offset
+ * due to the lack of regularity on spu packets)
+ */
+
+ int64_t (*got_spu_packet) (metronom_t *self, int64_t pts);
+
+ /*
+ * tell metronom about discontinuities.
+ *
+ * these functions are called due to a discontinuity detected at
+ * demux stage.
+ *
+ * there are different types of discontinuities:
+ *
+ * DISC_STREAMSTART : new stream starts, expect pts values to start
+ * from zero immediately
+ * DISC_RELATIVE : typically a wrap-around, expect pts with
+ * a specified offset from the former ones soon
+ * DISC_ABSOLUTE : typically a new menu stream (nav packets)
+ * pts will start from given value soon
+ * DISC_STREAMSEEK : used by video and audio decoder loop,
+ * when a buffer with BUF_FLAG_SEEK set is encountered;
+ * applies the necessary vpts offset for the seek in
+ * metronom, but keeps the vpts difference between
+ * audio and video, so that metronom doesn't cough
+ */
+ void (*handle_audio_discontinuity) (metronom_t *self, int type, int64_t disc_off);
+ void (*handle_video_discontinuity) (metronom_t *self, int type, int64_t disc_off);
+
+ /*
+ * set/get options for metronom, constants see below
+ */
+ void (*set_option) (metronom_t *self, int option, int64_t value);
+ int64_t (*get_option) (metronom_t *self, int option);
+
+ /*
+ * set a master metronom
+ * this is currently useful to sync independently generated streams
+ * (e.g. by post plugins) to the discontinuity domain of another
+ * metronom
+ */
+ void (*set_master) (metronom_t *self, metronom_t *master);
+
+ void (*exit) (metronom_t *self);
+
+#ifdef METRONOM_INTERNAL
+ /*
+ * metronom internal stuff
+ */
+ xine_t *xine;
+
+ metronom_t *master;
+
+ int64_t pts_per_smpls;
+
+ int64_t video_vpts;
+ int64_t spu_vpts;
+ int64_t audio_vpts;
+ int64_t audio_vpts_rmndr; /* the remainder for integer division */
+
+ int64_t vpts_offset;
+
+ int64_t video_drift;
+ int64_t video_drift_step;
+
+ int audio_samples;
+ int64_t audio_drift_step;
+
+ int64_t prebuffer;
+ int64_t av_offset;
+ int64_t spu_offset;
+
+ pthread_mutex_t lock;
+
+ int have_video;
+ int have_audio;
+ int video_discontinuity_count;
+ int audio_discontinuity_count;
+ int discontinuity_handled_count;
+ pthread_cond_t video_discontinuity_reached;
+ pthread_cond_t audio_discontinuity_reached;
+
+ int force_video_jump;
+ int force_audio_jump;
+
+ int64_t img_duration;
+ int img_cpt;
+ int64_t last_video_pts;
+ int64_t last_audio_pts;
+
+ int video_mode;
+#endif
+};
+
+/*
+ * metronom options
+ */
+
+#define METRONOM_AV_OFFSET 2
+#define METRONOM_ADJ_VPTS_OFFSET 3
+#define METRONOM_FRAME_DURATION 4
+#define METRONOM_SPU_OFFSET 5
+#define METRONOM_VPTS_OFFSET 6
+#define METRONOM_PREBUFFER 7
+
+metronom_t *_x_metronom_init (int have_video, int have_audio, xine_t *xine) XINE_MALLOC XINE_PROTECTED;
+
+/* FIXME: reorder this structure on the next cleanup to remove the dummies */
+struct metronom_clock_s {
+
+ /*
+ * set/get options for clock, constants see below
+ */
+ void (*set_option) (metronom_clock_t *self, int option, int64_t value);
+ int64_t (*get_option) (metronom_clock_t *self, int option);
+
+ /*
+ * system clock reference (SCR) functions
+ */
+
+#ifdef METRONOM_CLOCK_INTERNAL
+ /*
+ * start clock (no clock reset)
+ * at given pts
+ */
+ void (*start_clock) (metronom_clock_t *self, int64_t pts);
+
+
+ /*
+ * stop metronom clock
+ */
+ void (*stop_clock) (metronom_clock_t *self);
+
+
+ /*
+ * resume clock from where it was stopped
+ */
+ void (*resume_clock) (metronom_clock_t *self);
+#else
+ void *dummy1;
+ void *dummy2;
+ void *dummy3;
+#endif
+
+
+ /*
+ * get current clock value in vpts
+ */
+ int64_t (*get_current_time) (metronom_clock_t *self);
+
+
+ /*
+ * adjust master clock to external timer (e.g. audio hardware)
+ */
+ void (*adjust_clock) (metronom_clock_t *self, int64_t desired_pts);
+
+#ifdef METRONOM_CLOCK_INTERNAL
+ /*
+ * set clock speed
+ * for constants see xine_internal.h
+ */
+
+ int (*set_fine_speed) (metronom_clock_t *self, int speed);
+#else
+ void *dummy4;
+#endif
+
+ /*
+ * (un)register a System Clock Reference provider at the metronom
+ */
+ int (*register_scr) (metronom_clock_t *self, scr_plugin_t *scr);
+ void (*unregister_scr) (metronom_clock_t *self, scr_plugin_t *scr);
+
+#ifdef METRONOM_CLOCK_INTERNAL
+ void (*exit) (metronom_clock_t *self);
+
+ xine_t *xine;
+
+ scr_plugin_t *scr_master;
+ scr_plugin_t **scr_list;
+ pthread_t sync_thread;
+ int thread_running;
+ int scr_adjustable;
+#else
+ void *dummy5;
+ void *dummy6;
+ void *dummy7;
+ void *dummy8;
+ pthread_t dummy9;
+ int dummy10;
+ int dummy11;
+#endif
+
+ int speed;
+
+#ifdef METRONOM_CLOCK_INTERNAL
+ pthread_mutex_t lock;
+ pthread_cond_t cancel;
+#endif
+};
+
+metronom_clock_t *_x_metronom_clock_init(xine_t *xine) XINE_MALLOC XINE_PROTECTED;
+
+/*
+ * clock options
+ */
+
+#define CLOCK_SCR_ADJUSTABLE 1
+
+/*
+ * SCR (system clock reference) plugins
+ */
+
+struct scr_plugin_s
+{
+ int (*get_priority) (scr_plugin_t *self);
+
+ /*
+ * set/get clock speed
+ *
+ * for speed constants see xine_internal.h
+ * returns actual speed
+ */
+
+ int (*set_fine_speed) (scr_plugin_t *self, int speed);
+
+ void (*adjust) (scr_plugin_t *self, int64_t vpts);
+
+ void (*start) (scr_plugin_t *self, int64_t start_vpts);
+
+ int64_t (*get_current) (scr_plugin_t *self);
+
+ void (*exit) (scr_plugin_t *self);
+
+ metronom_clock_t *clock;
+
+ int interface_version;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif