1 /*****************************************************************************
2 * clock.c: Output modules synchronisation clock
3 *****************************************************************************
4 * Copyright (C) 2018-2019 VLC authors, VideoLAN and Videolabs SAS
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program 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 Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
24 #include <vlc_common.h>
29 #include "clock_internal.h"
31 struct vlc_clock_main_t
42 * system = ts * coeff / rate + offset
45 average_t coeff_avg
; /* Moving average to smooth out the instant coeff */
51 vlc_tick_t pause_date
;
53 unsigned wait_sync_ref_priority
;
54 clock_point_t wait_sync_ref
; /* When the master */
55 clock_point_t first_pcr
;
56 vlc_tick_t output_dejitter
; /* Delay used to absorb the output clock jitter */
57 vlc_tick_t input_dejitter
; /* Delay used to absorb the input jitter */
63 vlc_tick_t (*update
)(vlc_clock_t
*clock
, vlc_tick_t system_now
,
64 vlc_tick_t ts
, double rate
,
65 unsigned frame_rate
, unsigned frame_rate_base
);
66 void (*reset
)(vlc_clock_t
*clock
);
67 vlc_tick_t (*set_delay
)(vlc_clock_t
*clock
, vlc_tick_t delay
);
68 vlc_tick_t (*to_system_locked
)(vlc_clock_t
*clock
, vlc_tick_t system_now
,
69 vlc_tick_t ts
, double rate
);
71 vlc_clock_main_t
*owner
;
75 const struct vlc_clock_cbs
*cbs
;
79 static vlc_tick_t
main_stream_to_system(vlc_clock_main_t
*main_clock
,
82 if (main_clock
->offset
== VLC_TICK_INVALID
)
83 return VLC_TICK_INVALID
;
85 (ts
* main_clock
->coeff
/ main_clock
->rate
+ main_clock
->offset
);
88 static void vlc_clock_main_reset(vlc_clock_main_t
*main_clock
)
90 AvgReset(&main_clock
->coeff_avg
);
91 main_clock
->coeff
= 1.0f
;
92 main_clock
->rate
= 1.0f
;
93 main_clock
->offset
= VLC_TICK_INVALID
;
95 main_clock
->wait_sync_ref_priority
= UINT_MAX
;
96 main_clock
->wait_sync_ref
=
97 main_clock
->last
= clock_point_Create(VLC_TICK_INVALID
, VLC_TICK_INVALID
);
98 vlc_cond_broadcast(&main_clock
->cond
);
101 static inline void vlc_clock_on_update(vlc_clock_t
*clock
,
102 vlc_tick_t system_now
,
103 vlc_tick_t ts
, double rate
,
105 unsigned frame_rate_base
)
108 clock
->cbs
->on_update(system_now
, ts
, rate
, frame_rate
, frame_rate_base
,
112 static vlc_tick_t
vlc_clock_master_update(vlc_clock_t
*clock
,
113 vlc_tick_t system_now
,
114 vlc_tick_t original_ts
, double rate
,
116 unsigned frame_rate_base
)
118 vlc_clock_main_t
*main_clock
= clock
->owner
;
120 if (unlikely(original_ts
== VLC_TICK_INVALID
121 || system_now
== VLC_TICK_INVALID
))
122 return VLC_TICK_INVALID
;
124 const vlc_tick_t ts
= original_ts
+ clock
->delay
;
126 vlc_mutex_lock(&main_clock
->lock
);
128 /* If system_now is INT64_MAX, the update is forced, don't modify anything
129 * but only notify the new clock point. */
130 if (system_now
!= INT64_MAX
)
132 if (main_clock
->offset
!= VLC_TICK_INVALID
133 && ts
!= main_clock
->last
.stream
)
135 /* We have a reference so we can update coeff */
136 double instant_coeff
= (system_now
- main_clock
->last
.system
)
137 / (double)(ts
- main_clock
->last
.stream
);
138 if (rate
== main_clock
->rate
)
140 instant_coeff
*= rate
;
141 AvgUpdate(&main_clock
->coeff_avg
, instant_coeff
);
142 main_clock
->coeff
= AvgGet(&main_clock
->coeff_avg
);
147 main_clock
->wait_sync_ref_priority
= UINT_MAX
;
148 main_clock
->wait_sync_ref
=
149 clock_point_Create(VLC_TICK_INVALID
, VLC_TICK_INVALID
);
152 main_clock
->offset
= system_now
- ts
* main_clock
->coeff
/ rate
;
154 main_clock
->last
= clock_point_Create(system_now
, ts
);
156 main_clock
->rate
= rate
;
157 vlc_cond_broadcast(&main_clock
->cond
);
160 vlc_mutex_unlock(&main_clock
->lock
);
162 vlc_clock_on_update(clock
, system_now
, original_ts
, rate
, frame_rate
,
164 return VLC_TICK_INVALID
;
167 static void vlc_clock_master_reset(vlc_clock_t
*clock
)
169 vlc_clock_main_t
*main_clock
= clock
->owner
;
171 vlc_mutex_lock(&main_clock
->lock
);
172 vlc_clock_main_reset(main_clock
);
174 assert(main_clock
->delay
<= 0);
175 assert(clock
->delay
>= 0);
176 /* Move the delay from the slaves to the master */
177 if (clock
->delay
!= 0 && main_clock
->delay
!= 0)
179 vlc_tick_t delta
= clock
->delay
+ main_clock
->delay
;
182 clock
->delay
= delta
;
183 main_clock
->delay
= 0;
188 main_clock
->delay
= delta
;
192 vlc_mutex_unlock(&main_clock
->lock
);
194 vlc_clock_on_update(clock
, VLC_TICK_INVALID
, VLC_TICK_INVALID
, 1.f
, 0, 0);
197 static vlc_tick_t
vlc_clock_master_set_delay(vlc_clock_t
*clock
, vlc_tick_t delay
)
199 vlc_clock_main_t
*main_clock
= clock
->owner
;
200 vlc_mutex_lock(&main_clock
->lock
);
202 vlc_tick_t delta
= delay
- clock
->delay
;
206 /* The master clock is delayed */
207 main_clock
->delay
= 0;
208 clock
->delay
= delay
;
212 /* Delay all slaves clock instead of advancing the master one */
213 main_clock
->delay
= delta
;
216 assert(main_clock
->delay
<= 0);
217 assert(clock
->delay
>= 0);
219 vlc_cond_broadcast(&main_clock
->cond
);
220 vlc_mutex_unlock(&main_clock
->lock
);
225 vlc_clock_monotonic_to_system_locked(vlc_clock_t
*clock
, vlc_tick_t now
,
226 vlc_tick_t ts
, double rate
)
228 vlc_clock_main_t
*main_clock
= clock
->owner
;
230 if (clock
->priority
< main_clock
->wait_sync_ref_priority
)
232 /* XXX: This input_delay calculation is needed until we (finally) get
233 * ride of the input clock. This code is adapted from input_clock.c and
234 * is used to introduce the same delay than the input clock (first PTS
236 const vlc_tick_t pcr_delay
=
237 main_clock
->first_pcr
.system
== VLC_TICK_INVALID
? 0 :
238 (ts
- main_clock
->first_pcr
.stream
) / rate
+
239 main_clock
->first_pcr
.system
- now
;
241 const vlc_tick_t input_delay
= main_clock
->input_dejitter
+ pcr_delay
;
243 const vlc_tick_t delay
=
244 __MAX(input_delay
, main_clock
->output_dejitter
);
246 main_clock
->wait_sync_ref_priority
= clock
->priority
;
247 main_clock
->wait_sync_ref
= clock_point_Create(now
+ delay
, ts
);
249 return (ts
- main_clock
->wait_sync_ref
.stream
) / rate
250 + main_clock
->wait_sync_ref
.system
;
253 static vlc_tick_t
vlc_clock_slave_to_system_locked(vlc_clock_t
*clock
,
255 vlc_tick_t ts
, double rate
)
257 vlc_clock_main_t
*main_clock
= clock
->owner
;
258 if (main_clock
->pause_date
!= VLC_TICK_INVALID
)
261 vlc_tick_t system
= main_stream_to_system(main_clock
, ts
);
262 if (system
== VLC_TICK_INVALID
)
264 /* We don't have a master sync point, let's fallback to a monotonic ref
266 system
= vlc_clock_monotonic_to_system_locked(clock
, now
, ts
, rate
);
269 return system
+ (clock
->delay
- main_clock
->delay
) * rate
;
272 static vlc_tick_t
vlc_clock_master_to_system_locked(vlc_clock_t
*clock
,
274 vlc_tick_t ts
, double rate
)
276 vlc_clock_main_t
*main_clock
= clock
->owner
;
277 vlc_tick_t system
= main_stream_to_system(main_clock
, ts
);
278 if (system
== VLC_TICK_INVALID
)
280 /* We don't have a master sync point, let's fallback to a monotonic ref
282 system
= vlc_clock_monotonic_to_system_locked(clock
, now
, ts
, rate
);
285 return system
+ clock
->delay
* rate
;
288 static vlc_tick_t
vlc_clock_slave_update(vlc_clock_t
*clock
,
289 vlc_tick_t system_now
,
290 vlc_tick_t ts
, double rate
,
292 unsigned frame_rate_base
)
294 vlc_clock_main_t
*main_clock
= clock
->owner
;
295 vlc_mutex_lock(&main_clock
->lock
);
297 /* If system_now is INT64_MAX, the update is forced, don't modify anything
298 * but only notify the new clock point. */
299 vlc_tick_t computed
= system_now
== INT64_MAX
? INT64_MAX
300 : clock
->to_system_locked(clock
, system_now
, ts
, rate
);
302 vlc_mutex_unlock(&main_clock
->lock
);
304 vlc_clock_on_update(clock
, computed
, ts
, rate
, frame_rate
, frame_rate_base
);
305 return computed
!= INT64_MAX
? computed
- system_now
: INT64_MAX
;
308 static void vlc_clock_slave_reset(vlc_clock_t
*clock
)
310 vlc_clock_main_t
*main_clock
= clock
->owner
;
311 vlc_mutex_lock(&main_clock
->lock
);
312 main_clock
->wait_sync_ref_priority
= UINT_MAX
;
313 main_clock
->wait_sync_ref
=
314 clock_point_Create(VLC_TICK_INVALID
, VLC_TICK_INVALID
);
316 vlc_mutex_unlock(&main_clock
->lock
);
318 vlc_clock_on_update(clock
, VLC_TICK_INVALID
, VLC_TICK_INVALID
, 1.0f
, 0, 0);
321 static vlc_tick_t
vlc_clock_slave_set_delay(vlc_clock_t
*clock
, vlc_tick_t delay
)
323 vlc_clock_main_t
*main_clock
= clock
->owner
;
324 vlc_mutex_lock(&main_clock
->lock
);
326 clock
->delay
= delay
;
328 vlc_cond_broadcast(&main_clock
->cond
);
329 vlc_mutex_unlock(&main_clock
->lock
);
333 int vlc_clock_Wait(vlc_clock_t
*clock
, vlc_tick_t system_now
, vlc_tick_t ts
,
334 double rate
, vlc_tick_t max_duration
)
336 vlc_clock_main_t
*main_clock
= clock
->owner
;
337 vlc_mutex_lock(&main_clock
->lock
);
338 const vlc_tick_t max_deadline
=
339 max_duration
> 0 ? system_now
+ max_duration
: INT64_MAX
;
340 while (!main_clock
->abort
)
343 if (main_clock
->pause_date
!= VLC_TICK_INVALID
)
344 deadline
= INT64_MAX
;
346 deadline
= clock
->to_system_locked(clock
, system_now
, ts
, rate
);
347 deadline
= __MIN(deadline
, max_deadline
);
349 if (vlc_cond_timedwait(&main_clock
->cond
, &main_clock
->lock
, deadline
))
351 vlc_mutex_unlock(&main_clock
->lock
);
355 vlc_mutex_unlock(&main_clock
->lock
);
359 vlc_clock_main_t
*vlc_clock_main_New(void)
361 vlc_clock_main_t
*main_clock
= malloc(sizeof(vlc_clock_main_t
));
363 if (main_clock
== NULL
)
366 vlc_mutex_init(&main_clock
->lock
);
367 vlc_cond_init(&main_clock
->cond
);
368 main_clock
->master
= NULL
;
371 main_clock
->coeff
= 1.0f
;
372 main_clock
->rate
= 1.0f
;
373 main_clock
->offset
= VLC_TICK_INVALID
;
374 main_clock
->delay
= 0;
376 main_clock
->first_pcr
=
377 clock_point_Create(VLC_TICK_INVALID
, VLC_TICK_INVALID
);
378 main_clock
->wait_sync_ref_priority
= UINT_MAX
;
379 main_clock
->wait_sync_ref
= main_clock
->last
=
380 clock_point_Create(VLC_TICK_INVALID
, VLC_TICK_INVALID
);
382 main_clock
->pause_date
= VLC_TICK_INVALID
;
383 main_clock
->input_dejitter
= DEFAULT_PTS_DELAY
;
384 main_clock
->output_dejitter
= AOUT_MAX_PTS_ADVANCE
* 2;
385 main_clock
->abort
= false;
387 AvgInit(&main_clock
->coeff_avg
, 10);
392 void vlc_clock_main_Abort(vlc_clock_main_t
*main_clock
)
394 vlc_mutex_lock(&main_clock
->lock
);
395 main_clock
->abort
= true;
396 vlc_cond_broadcast(&main_clock
->cond
);
398 vlc_mutex_unlock(&main_clock
->lock
);
401 void vlc_clock_main_Reset(vlc_clock_main_t
*main_clock
)
403 vlc_mutex_lock(&main_clock
->lock
);
404 vlc_clock_main_reset(main_clock
);
405 main_clock
->first_pcr
=
406 clock_point_Create(VLC_TICK_INVALID
, VLC_TICK_INVALID
);
407 vlc_mutex_unlock(&main_clock
->lock
);
410 void vlc_clock_main_SetFirstPcr(vlc_clock_main_t
*main_clock
,
411 vlc_tick_t system_now
, vlc_tick_t ts
)
413 vlc_mutex_lock(&main_clock
->lock
);
414 if (main_clock
->first_pcr
.system
== VLC_TICK_INVALID
)
416 main_clock
->first_pcr
= clock_point_Create(system_now
, ts
);
417 main_clock
->wait_sync_ref_priority
= UINT_MAX
;
418 main_clock
->wait_sync_ref
=
419 clock_point_Create(VLC_TICK_INVALID
, VLC_TICK_INVALID
);
421 vlc_mutex_unlock(&main_clock
->lock
);
424 void vlc_clock_main_SetInputDejitter(vlc_clock_main_t
*main_clock
,
427 vlc_mutex_lock(&main_clock
->lock
);
428 main_clock
->input_dejitter
= delay
;
429 vlc_mutex_unlock(&main_clock
->lock
);
432 void vlc_clock_main_SetDejitter(vlc_clock_main_t
*main_clock
,
435 vlc_mutex_lock(&main_clock
->lock
);
436 main_clock
->output_dejitter
= dejitter
;
437 vlc_mutex_unlock(&main_clock
->lock
);
440 void vlc_clock_main_ChangePause(vlc_clock_main_t
*main_clock
, vlc_tick_t now
,
443 vlc_mutex_lock(&main_clock
->lock
);
444 assert(paused
== (main_clock
->pause_date
== VLC_TICK_INVALID
));
447 main_clock
->pause_date
= now
;
451 * Only apply a delay if the clock has a reference point to avoid
452 * messing up the timings if the stream was paused then seeked
454 const vlc_tick_t delay
= now
- main_clock
->pause_date
;
455 if (main_clock
->offset
!= VLC_TICK_INVALID
)
457 main_clock
->last
.system
+= delay
;
458 main_clock
->offset
+= delay
;
460 if (main_clock
->first_pcr
.system
!= VLC_TICK_INVALID
)
461 main_clock
->first_pcr
.system
+= delay
;
462 if (main_clock
->wait_sync_ref
.system
!= VLC_TICK_INVALID
)
463 main_clock
->wait_sync_ref
.system
+= delay
;
464 main_clock
->pause_date
= VLC_TICK_INVALID
;
465 vlc_cond_broadcast(&main_clock
->cond
);
467 vlc_mutex_unlock(&main_clock
->lock
);
470 void vlc_clock_main_Delete(vlc_clock_main_t
*main_clock
)
472 vlc_mutex_destroy(&main_clock
->lock
);
473 vlc_cond_destroy(&main_clock
->cond
);
474 assert(main_clock
->rc
== 1);
478 vlc_tick_t
vlc_clock_Update(vlc_clock_t
*clock
, vlc_tick_t system_now
,
479 vlc_tick_t ts
, double rate
)
481 return clock
->update(clock
, system_now
, ts
, rate
, 0, 0);
484 vlc_tick_t
vlc_clock_UpdateVideo(vlc_clock_t
*clock
, vlc_tick_t system_now
,
485 vlc_tick_t ts
, double rate
,
486 unsigned frame_rate
, unsigned frame_rate_base
)
488 return clock
->update(clock
, system_now
, ts
, rate
, frame_rate
, frame_rate_base
);
491 void vlc_clock_Reset(vlc_clock_t
*clock
)
496 vlc_tick_t
vlc_clock_SetDelay(vlc_clock_t
*clock
, vlc_tick_t delay
)
498 return clock
->set_delay(clock
, delay
);
501 vlc_tick_t
vlc_clock_ConvertToSystem(vlc_clock_t
*clock
, vlc_tick_t system_now
,
502 vlc_tick_t ts
, double rate
)
504 vlc_clock_main_t
*main_clock
= clock
->owner
;
505 vlc_mutex_lock(&main_clock
->lock
);
506 vlc_tick_t system
= clock
->to_system_locked(clock
, system_now
, ts
, rate
);
507 vlc_mutex_unlock(&main_clock
->lock
);
511 void vlc_clock_ConvertArrayToSystem(vlc_clock_t
*clock
, vlc_tick_t system_now
,
512 vlc_tick_t
*ts_array
, size_t ts_count
,
515 vlc_clock_main_t
*main_clock
= clock
->owner
;
516 vlc_mutex_lock(&main_clock
->lock
);
517 for (size_t i
= 0; i
< ts_count
; ++i
)
518 ts_array
[i
] = clock
->to_system_locked(clock
, system_now
, ts_array
[i
],
520 vlc_mutex_unlock(&main_clock
->lock
);
523 static void vlc_clock_set_master_callbacks(vlc_clock_t
*clock
)
525 clock
->update
= vlc_clock_master_update
;
526 clock
->reset
= vlc_clock_master_reset
;
527 clock
->set_delay
= vlc_clock_master_set_delay
;
528 clock
->to_system_locked
= vlc_clock_master_to_system_locked
;
531 static void vlc_clock_set_slave_callbacks(vlc_clock_t
*clock
)
533 clock
->update
= vlc_clock_slave_update
;
534 clock
->reset
= vlc_clock_slave_reset
;
535 clock
->set_delay
= vlc_clock_slave_set_delay
;
536 clock
->to_system_locked
= vlc_clock_slave_to_system_locked
;
539 static vlc_clock_t
*vlc_clock_main_Create(vlc_clock_main_t
*main_clock
,
541 const struct vlc_clock_cbs
*cbs
,
544 vlc_clock_t
*clock
= malloc(sizeof(vlc_clock_t
));
548 clock
->owner
= main_clock
;
551 clock
->cbs_data
= cbs_data
;
552 clock
->priority
= priority
;
553 assert(!cbs
|| cbs
->on_update
);
558 vlc_clock_t
*vlc_clock_main_CreateMaster(vlc_clock_main_t
*main_clock
,
559 const struct vlc_clock_cbs
*cbs
,
562 /* The master has always the 0 priority */
563 vlc_clock_t
*clock
= vlc_clock_main_Create(main_clock
, 0, cbs
, cbs_data
);
567 vlc_mutex_lock(&main_clock
->lock
);
568 if (main_clock
->master
!= NULL
)
570 vlc_clock_master_reset(main_clock
->master
);
571 vlc_clock_set_slave_callbacks(main_clock
->master
);
573 vlc_clock_set_master_callbacks(clock
);
574 main_clock
->master
= clock
;
576 vlc_mutex_unlock(&main_clock
->lock
);
581 vlc_clock_t
*vlc_clock_main_CreateSlave(vlc_clock_main_t
*main_clock
,
582 enum es_format_category_e cat
,
583 const struct vlc_clock_cbs
*cbs
,
586 /* SPU outputs should have lower priority than VIDEO outputs since they
587 * necessarily depend on a VIDEO output. This mean that a SPU reference
588 * point will always be overridden by AUDIO or VIDEO outputs. Cf.
589 * vlc_clock_monotonic_to_system_locked */
603 vlc_clock_t
*clock
= vlc_clock_main_Create(main_clock
, priority
, cbs
,
608 vlc_mutex_lock(&main_clock
->lock
);
609 vlc_clock_set_slave_callbacks(clock
);
611 vlc_mutex_unlock(&main_clock
->lock
);
616 vlc_clock_t
*vlc_clock_CreateSlave(const vlc_clock_t
*clock
,
617 enum es_format_category_e cat
)
619 return vlc_clock_main_CreateSlave(clock
->owner
, cat
, NULL
, NULL
);
622 void vlc_clock_main_SetMaster(vlc_clock_main_t
*main_clock
, vlc_clock_t
*clock
)
624 vlc_mutex_lock(&main_clock
->lock
);
625 if (main_clock
->master
!= NULL
)
627 vlc_clock_master_reset(main_clock
->master
);
628 vlc_clock_set_slave_callbacks(main_clock
->master
);
630 vlc_clock_set_master_callbacks(clock
);
631 main_clock
->master
= clock
;
632 vlc_mutex_unlock(&main_clock
->lock
);
636 void vlc_clock_Delete(vlc_clock_t
*clock
)
638 vlc_clock_main_t
*main_clock
= clock
->owner
;
639 vlc_mutex_lock(&main_clock
->lock
);
640 if (clock
== main_clock
->master
)
642 vlc_clock_main_reset(main_clock
);
643 main_clock
->master
= NULL
;
646 vlc_mutex_unlock(&main_clock
->lock
);