1 /*
2  * Copyright (C) 2000-2019 the xine project
3  *
4  * This file is part of xine, a free video player.
5  *
6  * xine is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * xine is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19  *
20  * metronom: general pts => virtual calculation/assoc
21  *
22  * virtual pts: unit 1/90000 sec, always increasing
23  *              can be used for synchronization
24  *              video/audio frame with same pts also have same vpts
25  *              but pts is likely to differ from vpts
26  *
27  * the basic idea is:
28  *    video_pts + video_wrap_offset = video_vpts
29  *    audio_pts + audio_wrap_offset = audio_vpts
30  *
31  *  - video_wrap_offset should be equal to audio_wrap_offset as to have
32  *    perfect audio and video sync. They will differ on brief periods due
33  *    discontinuity correction.
34  *  - metronom should also interpolate vpts values most of the time as
35  *    video_pts and audio_vpts are not given for every frame.
36  *  - corrections to the frame rate may be needed to cope with bad
37  *    encoded streams.
38  */
39 
40 #ifndef HAVE_METRONOM_H
41 #define HAVE_METRONOM_H
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 #include <pthread.h>
48 
49 #include <xine/video_out.h>
50 #include <xine.h>
51 
52 typedef struct metronom_s metronom_t ;
53 typedef struct metronom_clock_s metronom_clock_t;
54 typedef struct scr_plugin_s scr_plugin_t;
55 
56 /* metronom prebuffer can be adjusted with XINE_PARAM_METRONOM_PREBUFFER.
57  * it sets how much the first video/audio frame should be delayed to
58  * have some prebuffering at the output layers. reducing this value (about
59  * 1/8 sec) may result in faster seeking (good to simulate play backwards,
60  * for example).
61  */
62 #define PREBUFFER_PTS_OFFSET  12000
63 
64   /* see below */
65 #define DISC_STREAMSTART 0
66 #define DISC_RELATIVE    1
67 #define DISC_ABSOLUTE    2
68 #define DISC_STREAMSEEK  3
69 #define DISC_GAPLESS     4
70 
71 struct metronom_s {
72 
73   /*
74    * called by audio output driver to inform metronom about current audio
75    * samplerate
76    *
77    * parameter pts_per_smpls : 1/90000 sec per 65536 samples
78    */
79   void (*set_audio_rate) (metronom_t *self, int64_t pts_per_smpls);
80 
81   /*
82    * called by video output driver for *every* frame
83    *
84    * parameter frame containing pts, scr, ... information
85    *
86    * will set vpts field in frame
87    *
88    * this function will also update video_wrap_offset if a discontinuity
89    * is detected (read the comentaries below about discontinuities).
90    *
91    */
92 
93   void (*got_video_frame) (metronom_t *self, vo_frame_t *frame);
94 
95   /*
96    * called by audio output driver whenever audio samples are delivered to it
97    *
98    * parameter pts      : pts for audio data if known, 0 otherwise
99    *           nsamples : number of samples delivered
100    *
101    * return value: virtual pts for audio data
102    *
103    * this function will also update audio_wrap_offset if a discontinuity
104    * is detected (read the comentaries below about discontinuities).
105    *
106    */
107 
108   int64_t (*got_audio_samples) (metronom_t *self, int64_t pts,
109 				int nsamples);
110 
111   /*
112    * called by SPU decoder whenever a packet is delivered to it
113    *
114    * parameter pts      : pts for SPU packet if known, 0 otherwise
115    *
116    * return value: virtual pts for SPU packet
117    * (this is the only pts to vpts function that cannot update the wrap_offset
118    * due to the lack of regularity on spu packets)
119    */
120 
121   int64_t (*got_spu_packet) (metronom_t *self, int64_t pts);
122 
123   /*
124    * tell metronom about discontinuities.
125    *
126    * these functions are called due to a discontinuity detected at
127    * demux stage.
128    *
129    * there are different types of discontinuities:
130    *
131    * DISC_STREAMSTART : new stream starts, expect pts values to start
132    *                    from zero immediately
133    * DISC_RELATIVE    : typically a wrap-around, expect pts with
134    *                    a specified offset from the former ones soon
135    * DISC_ABSOLUTE    : typically a new menu stream (nav packets)
136    *                    pts will start from given value soon.
137    *                    this will try a seamless transition even if decoder
138    *                    reorders frames around it.
139    * DISC_STREAMSEEK  : used by video and audio decoder loop,
140    *                    when a buffer with BUF_FLAG_SEEK set is encountered;
141    *                    applies the necessary vpts offset for the seek in
142    *                    metronom, but keeps the vpts difference between
143    *                    audio and video, so that metronom doesn't cough
144    * DISC_GAPLESS     : wait until it is safe to start next gapless stream.
145    *                    used internally by xine_play ().
146    */
147   void (*handle_audio_discontinuity) (metronom_t *self, int type, int64_t disc_off);
148   void (*handle_video_discontinuity) (metronom_t *self, int type, int64_t disc_off);
149 
150   /*
151    * set/get options for metronom, constants see below
152    */
153   void (*set_option) (metronom_t *self, int option, int64_t value);
154   int64_t (*get_option) (metronom_t *self, int option);
155 
156   /*
157    * set a master metronom
158    * this is currently useful to sync independently generated streams
159    * (e.g. by post plugins) to the discontinuity domain of another
160    * metronom
161    */
162   void (*set_master) (metronom_t *self, metronom_t *master);
163 
164   void (*exit) (metronom_t *self);
165 
166 };
167 
168 /*
169  * metronom options
170  */
171 
172 #define METRONOM_AV_OFFSET        2
173 #define METRONOM_ADJ_VPTS_OFFSET  3
174 #define METRONOM_FRAME_DURATION   4
175 #define METRONOM_SPU_OFFSET       5
176 #define METRONOM_VPTS_OFFSET      6
177 #define METRONOM_PREBUFFER        7
178 #define METRONOM_VPTS             8
179 /* METRONOM_LOCK can be used to lock metronom when multiple options needs to be fetched atomically (ex. VPTS_OFFSET and AV_OFFSET).
180  * example:
181  *   metronom->set_option(metronom, METRONOM_LOCK, 1);
182  *   vpts_offset = metronom->get_option(metronom, METRONOM_VPTS_OFFSET|METRONOM_NO_LOCK);
183  *   av_offset   = metronom->get_option(metronom, METRONOM_AV_OFFSET|METRONOM_NO_LOCK);
184  *   metronom->set_option(metronom, METRONOM_LOCK, 0);
185  */
186 #define METRONOM_LOCK             9
187 /* Returns 0 (not waiting), 1 (waiting for audio discontinuity), 2 (waiting for video discontinuity). */
188 #define METRONOM_WAITING          10
189 /* Nasty input_vdr helper. Inserts an immediate absolute discontinuity,
190  * old style without pts reorder fix. */
191 #define METRONOM_VDR_TRICK_PTS    11
192 #define METRONOM_NO_LOCK          0x8000
193 
194 typedef void xine_speed_change_cb_t (void *user_data, int new_speed);
195 
196 metronom_t *_x_metronom_init (int have_video, int have_audio, xine_t *xine) XINE_MALLOC XINE_PROTECTED;
197 
198 /* FIXME: reorder this structure on the next cleanup to remove the dummies */
199 struct metronom_clock_s {
200 
201   /*
202    * set/get options for clock, constants see below
203    */
204   void (*set_option) (metronom_clock_t *self, int option, int64_t value);
205   int64_t (*get_option) (metronom_clock_t *self, int option);
206 
207   /*
208    * system clock reference (SCR) functions
209    */
210 
211 #ifdef METRONOM_CLOCK_INTERNAL
212   /*
213    * start clock (no clock reset)
214    * at given pts
215    */
216   void (*start_clock) (metronom_clock_t *self, int64_t pts);
217 
218 
219   /*
220    * stop metronom clock
221    */
222   void (*stop_clock) (metronom_clock_t *self);
223 
224 
225   /*
226    * resume clock from where it was stopped
227    */
228   void (*resume_clock) (metronom_clock_t *self);
229 #else
230   void *dummy1;
231   void *dummy2;
232   void *dummy3;
233 #endif
234 
235 
236   /*
237    * get current clock value in vpts
238    */
239   int64_t (*get_current_time) (metronom_clock_t *self);
240 
241 
242   /*
243    * adjust master clock to external timer (e.g. audio hardware)
244    */
245   void (*adjust_clock) (metronom_clock_t *self, int64_t desired_pts);
246 
247 #ifdef METRONOM_CLOCK_INTERNAL
248   /*
249    * set clock speed
250    * for constants see xine_internal.h
251    */
252 
253   int (*set_fine_speed) (metronom_clock_t *self, int speed);
254 #else
255   void *dummy4;
256 #endif
257 
258   /*
259    * (un)register a System Clock Reference provider at the metronom
260    */
261   int    (*register_scr) (metronom_clock_t *self, scr_plugin_t *scr);
262   void (*unregister_scr) (metronom_clock_t *self, scr_plugin_t *scr);
263 
264 #ifdef METRONOM_CLOCK_INTERNAL
265   void (*exit) (metronom_clock_t *self);
266 
267   xine_t         *xine;
268 
269   scr_plugin_t   *scr_master;
270   scr_plugin_t  **scr_list;
271   pthread_t       sync_thread;
272   int             thread_running;
273   int             scr_adjustable;
274 #else
275   void *dummy5;
276   void *dummy6;
277   void *dummy7;
278   void *dummy8;
279   pthread_t dummy9;
280   int dummy10;
281   int dummy11;
282 #endif
283 
284   int speed;
285 
286   void (*register_speed_change_callback)
287     (metronom_clock_t *self, xine_speed_change_cb_t *callback, void *user_data);
288   void (*unregister_speed_change_callback)
289     (metronom_clock_t *self, xine_speed_change_cb_t *callback, void *user_data);
290 
291 #ifdef METRONOM_CLOCK_INTERNAL
292   pthread_mutex_t lock;
293   pthread_cond_t  cancel;
294 #endif
295 };
296 
297 metronom_clock_t *_x_metronom_clock_init(xine_t *xine) XINE_MALLOC XINE_PROTECTED;
298 
299 /*
300  * clock options
301  */
302 
303 #define CLOCK_SCR_ADJUSTABLE   1
304 
305 /*
306  * SCR (system clock reference) plugins
307  */
308 
309 struct scr_plugin_s
310 {
311   int (*get_priority) (scr_plugin_t *self);
312 
313   /*
314    * set/get clock speed
315    *
316    * for speed constants see xine_internal.h
317    * returns actual speed
318    */
319 
320   int (*set_fine_speed) (scr_plugin_t *self, int speed);
321 
322   void (*adjust) (scr_plugin_t *self, int64_t vpts);
323 
324   void (*start) (scr_plugin_t *self, int64_t start_vpts);
325 
326   int64_t (*get_current) (scr_plugin_t *self);
327 
328   void (*exit) (scr_plugin_t *self);
329 
330   metronom_clock_t *clock;
331 
332   int interface_version;
333 };
334 
335 #ifdef __cplusplus
336 }
337 #endif
338 
339 #endif
340