medialib: fs: Ensure SD are destroyed first
[vlc.git] / src / clock / clock.c
blob43c44bed6e400428bc9529040876d2198f329b1f
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 *****************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 # include "config.h"
22 #endif
24 #include <vlc_common.h>
25 #include <vlc_aout.h>
26 #include <assert.h>
27 #include <limits.h>
28 #include "clock.h"
29 #include "clock_internal.h"
31 struct vlc_clock_main_t
33 vlc_mutex_t lock;
34 vlc_cond_t cond;
36 vlc_clock_t *master;
38 unsigned rc;
40 /**
41 * Linear function
42 * system = ts * coeff / rate + offset
44 clock_point_t last;
45 average_t coeff_avg; /* Moving average to smooth out the instant coeff */
46 double rate;
47 double coeff;
48 vlc_tick_t offset;
49 vlc_tick_t delay;
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 */
58 bool abort;
61 struct vlc_clock_t
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;
72 vlc_tick_t delay;
73 unsigned priority;
75 const struct vlc_clock_cbs *cbs;
76 void *cbs_data;
79 static vlc_tick_t main_stream_to_system(vlc_clock_main_t *main_clock,
80 vlc_tick_t ts)
82 if (main_clock->offset == VLC_TICK_INVALID)
83 return VLC_TICK_INVALID;
84 return (vlc_tick_t)
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,
104 unsigned frame_rate,
105 unsigned frame_rate_base)
107 if (clock->cbs)
108 clock->cbs->on_update(system_now, ts, rate, frame_rate, frame_rate_base,
109 clock->cbs_data);
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,
115 unsigned frame_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);
145 else
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,
163 frame_rate_base);
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;
180 if (delta > 0)
182 clock->delay = delta;
183 main_clock->delay = 0;
185 else
187 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;
204 if (delta > 0)
206 /* The master clock is delayed */
207 main_clock->delay = 0;
208 clock->delay = delay;
210 else
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);
221 return delta;
224 static vlc_tick_t
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
235 * - first PCR). */
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,
254 vlc_tick_t now,
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)
259 return INT64_MAX;
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
265 * point */
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,
273 vlc_tick_t now,
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
281 * point */
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,
291 unsigned frame_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);
330 return 0;
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)
342 vlc_tick_t deadline;
343 if (main_clock->pause_date != VLC_TICK_INVALID)
344 deadline = INT64_MAX;
345 else
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);
352 return 0;
355 vlc_mutex_unlock(&main_clock->lock);
356 return -1;
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)
364 return NULL;
366 vlc_mutex_init(&main_clock->lock);
367 vlc_cond_init(&main_clock->cond);
368 main_clock->master = NULL;
369 main_clock->rc = 1;
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);
389 return main_clock;
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,
425 vlc_tick_t delay)
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,
433 vlc_tick_t dejitter)
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,
441 bool paused)
443 vlc_mutex_lock(&main_clock->lock);
444 assert(paused == (main_clock->pause_date == VLC_TICK_INVALID));
446 if (paused)
447 main_clock->pause_date = now;
448 else
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);
475 free(main_clock);
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)
493 clock->reset(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);
508 return system;
511 void vlc_clock_ConvertArrayToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
512 vlc_tick_t *ts_array, size_t ts_count,
513 double rate)
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],
519 rate);
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,
540 unsigned priority,
541 const struct vlc_clock_cbs *cbs,
542 void *cbs_data)
544 vlc_clock_t *clock = malloc(sizeof(vlc_clock_t));
545 if (clock == NULL)
546 return NULL;
548 clock->owner = main_clock;
549 clock->delay = 0;
550 clock->cbs = cbs;
551 clock->cbs_data = cbs_data;
552 clock->priority = priority;
553 assert(!cbs || cbs->on_update);
555 return clock;
558 vlc_clock_t *vlc_clock_main_CreateMaster(vlc_clock_main_t *main_clock,
559 const struct vlc_clock_cbs *cbs,
560 void *cbs_data)
562 /* The master has always the 0 priority */
563 vlc_clock_t *clock = vlc_clock_main_Create(main_clock, 0, cbs, cbs_data);
564 if (!clock)
565 return NULL;
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;
575 main_clock->rc++;
576 vlc_mutex_unlock(&main_clock->lock);
578 return clock;
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,
584 void *cbs_data)
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 */
590 unsigned priority;
591 switch (cat)
593 case VIDEO_ES:
594 case AUDIO_ES:
595 priority = 1;
596 break;
597 case SPU_ES:
598 default:
599 priority = 2;
600 break;
603 vlc_clock_t *clock = vlc_clock_main_Create(main_clock, priority, cbs,
604 cbs_data);
605 if (!clock)
606 return NULL;
608 vlc_mutex_lock(&main_clock->lock);
609 vlc_clock_set_slave_callbacks(clock);
610 main_clock->rc++;
611 vlc_mutex_unlock(&main_clock->lock);
613 return clock;
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;
645 main_clock->rc--;
646 vlc_mutex_unlock(&main_clock->lock);
647 free(clock);