[vlc-devel] [PATCH 1/2] RFC: clock: propagate input dejitter/buffering delay to the output clock (FIXUP)
Thomas Guillem
thomas at gllm.fr
Thu Feb 14 17:49:07 CET 2019
This patch invalidate "RFC: output_clock: respect first pts delay (FIXUP)" and
is applied on top of the
https://code.videolan.org/jbk/vlc/commits/clock-core/26 branch.
The dejitter of the vlc_clock is the MAX between the dejitter set by the master
output (currently: 2 * AOUT_MAX_PTS_ADVANCE = 80ms by default) and the input
delay. The input delay is now the same than with the input_clock, that is:
Difference between the first pcr and the first pts, at a given time, taking
into account the buffer duration and the dejitter value set by the demux. Not
invented anything here, I just looked at the input_clock.c code.
---
src/audio_output/output.c | 2 +-
src/clock/clock.c | 84 ++++++++++++++++++++++++---------------
src/clock/clock.h | 8 +++-
src/input/es_out.c | 22 ++++++++--
4 files changed, 76 insertions(+), 40 deletions(-)
diff --git a/src/audio_output/output.c b/src/audio_output/output.c
index 8c355368f8..8b1b16c6dd 100644
--- a/src/audio_output/output.c
+++ b/src/audio_output/output.c
@@ -579,7 +579,7 @@ int aout_OutputNew (audio_output_t *aout, audio_sample_format_t *restrict fmt,
aout_OutputLock(aout);
vlc_tick_t period = AOUT_MAX_PTS_ADVANCE;
int ret = aout->start(aout, fmt, &period);
- vlc_clock_SetDejitter(owner->sync.clock, period * 2, 100);
+ vlc_clock_SetDejitter(owner->sync.clock, period * 2);
aout_OutputUnlock(aout);
if (ret)
{
diff --git a/src/clock/clock.c b/src/clock/clock.c
index 8308c0ffc4..8aaaa458eb 100644
--- a/src/clock/clock.c
+++ b/src/clock/clock.c
@@ -22,6 +22,7 @@
#endif
#include <vlc_common.h>
+#include <vlc_aout.h>
#include <assert.h>
#include "clock.h"
#include "clock_internal.h"
@@ -49,7 +50,9 @@ struct vlc_clock_main_t
vlc_tick_t pause_date;
clock_point_t wait_sync_ref; /* When the master */
- vlc_tick_t dejitter; /* Delay used to absorb the clock jitter */
+ clock_point_t first_pcr;
+ vlc_tick_t output_dejitter; /* Delay used to absorb the output clock jitter */
+ vlc_tick_t input_dejitter; /* Delay used to absorb the input jitter */
bool abort;
};
@@ -60,12 +63,13 @@ struct vlc_clock_t
void (*reset)(vlc_clock_t * clock);
void (*pause)(vlc_clock_t * clock, vlc_tick_t system_now, bool paused);
vlc_tick_t (*set_delay)(vlc_clock_t * clock, vlc_tick_t delay);
- void (*set_dejitter)(vlc_clock_t * clock, vlc_tick_t delay, int cr_avg);
+ void (*set_dejitter)(vlc_clock_t * clock, vlc_tick_t delay);
vlc_tick_t (*to_system_locked)(vlc_clock_t * clock, vlc_tick_t system_now,
vlc_tick_t pts);
vlc_clock_main_t * owner;
vlc_tick_t delay;
+ vlc_tick_t dejitter;
};
static vlc_tick_t main_system_to_stream(vlc_clock_main_t * main_clock,
@@ -177,14 +181,16 @@ static void vlc_clock_master_pause(vlc_clock_t * clock, vlc_tick_t now, bool pau
* Only apply a delay if the clock has a reference point to avoid
* messing up the timings if the stream was paused then seeked
*/
- if (main_clock->offset != VLC_TICK_INVALID ||
- (main_clock->wait_sync_ref.stream != VLC_TICK_INVALID ||
- main_clock->wait_sync_ref.system != VLC_TICK_INVALID))
+ const vlc_tick_t delay = now - main_clock->pause_date;
+ if (main_clock->offset != VLC_TICK_INVALID)
{
- const vlc_tick_t delay = now - main_clock->pause_date;
main_clock->last.system += delay;
main_clock->offset += delay;
}
+ if (main_clock->first_pcr.system != VLC_TICK_INVALID)
+ main_clock->first_pcr.system += delay;
+ if (main_clock->wait_sync_ref.system != VLC_TICK_INVALID)
+ main_clock->wait_sync_ref.system += delay;
main_clock->pause_date = VLC_TICK_INVALID;
vlc_cond_broadcast(&main_clock->cond);
}
@@ -242,29 +248,17 @@ static vlc_tick_t vlc_clock_to_stream(vlc_clock_t * clock, vlc_tick_t system)
return pts;
}
-static void vlc_clock_master_set_dejitter(vlc_clock_t * clock, vlc_tick_t delay, int cr_avg)
-{
- VLC_UNUSED(cr_avg);
- vlc_clock_main_t * main_clock = clock->owner;
-
- vlc_mutex_lock(&main_clock->lock);
- main_clock->dejitter = delay;
- vlc_mutex_unlock(&main_clock->lock);
-}
-
-static vlc_tick_t vlc_clock_get_dejitter(vlc_clock_t * clock)
+static void vlc_clock_master_set_dejitter(vlc_clock_t * clock, vlc_tick_t delay)
{
vlc_clock_main_t * main_clock = clock->owner;
- vlc_tick_t dejitter;
vlc_mutex_lock(&main_clock->lock);
- dejitter = main_clock->dejitter;
+ main_clock->output_dejitter = delay;
vlc_mutex_unlock(&main_clock->lock);
- return dejitter;
}
static vlc_tick_t vlc_clock_main_to_system_locked(vlc_clock_main_t * main_clock,
- vlc_tick_t now, vlc_tick_t pts)
+ vlc_tick_t now, vlc_tick_t pts)
{
vlc_tick_t system = main_stream_to_system(main_clock, pts);
if (system == VLC_TICK_INVALID)
@@ -276,8 +270,15 @@ static vlc_tick_t vlc_clock_main_to_system_locked(vlc_clock_main_t * main_clock,
if (main_clock->wait_sync_ref.stream == VLC_TICK_INVALID ||
main_clock->wait_sync_ref.system == VLC_TICK_INVALID)
{
- main_clock->wait_sync_ref =
- clock_point_Create(pts, now + main_clock->dejitter);
+ const vlc_tick_t pcr_delay =
+ main_clock->first_pcr.system != VLC_TICK_INVALID ?
+ pts - main_clock->first_pcr.stream + main_clock->first_pcr.system - now : 0;
+
+ const vlc_tick_t input_delay = main_clock->input_dejitter + pcr_delay;
+ const vlc_tick_t delay =
+ __MAX(input_delay, main_clock->output_dejitter);
+
+ main_clock->wait_sync_ref = clock_point_Create(pts, now + delay);
}
system = (pts - main_clock->wait_sync_ref.stream) / main_clock->rate;
system += main_clock->wait_sync_ref.system;
@@ -373,11 +374,10 @@ int vlc_clock_Wait(vlc_clock_t * clock, vlc_tick_t pts, vlc_tick_t max_duration)
return 1;
}
-static void vlc_clock_slave_set_dejitter(vlc_clock_t * clock, vlc_tick_t delay, int cr_avg)
+static void vlc_clock_slave_set_dejitter(vlc_clock_t * clock, vlc_tick_t delay)
{
VLC_UNUSED(clock);
VLC_UNUSED(delay);
- VLC_UNUSED(cr_avg);
}
@@ -398,11 +398,13 @@ vlc_clock_main_t * vlc_clock_main_New(void)
main_clock->offset = VLC_TICK_INVALID;
main_clock->delay = 0;
+ main_clock->first_pcr = clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
main_clock->wait_sync_ref =
main_clock->last = clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
main_clock->pause_date = VLC_TICK_INVALID;
- main_clock->dejitter = 40000;
+ main_clock->input_dejitter = DEFAULT_PTS_DELAY;
+ main_clock->output_dejitter = AOUT_MAX_PTS_ADVANCE * 2;
main_clock->abort = false;
AvgInit(&main_clock->coeff_avg, 10);
@@ -423,6 +425,27 @@ void vlc_clock_main_Reset(vlc_clock_main_t * main_clock)
{
vlc_mutex_lock(&main_clock->lock);
vlc_clock_main_reset(main_clock);
+ main_clock->first_pcr = clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
+ vlc_mutex_unlock(&main_clock->lock);
+}
+
+void vlc_clock_main_SetFirstPcr(vlc_clock_main_t * main_clock,
+ vlc_tick_t system_now, vlc_tick_t pts)
+{
+ vlc_mutex_lock(&main_clock->lock);
+ if (main_clock->first_pcr.system == VLC_TICK_INVALID)
+ {
+ main_clock->first_pcr = clock_point_Create(pts, system_now);
+ main_clock->wait_sync_ref =
+ clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
+ }
+ vlc_mutex_unlock(&main_clock->lock);
+}
+
+void vlc_clock_main_SetInputDejitter(vlc_clock_main_t * main_clock, vlc_tick_t delay)
+{
+ vlc_mutex_lock(&main_clock->lock);
+ main_clock->input_dejitter = delay;
vlc_mutex_unlock(&main_clock->lock);
}
@@ -485,14 +508,9 @@ vlc_tick_t vlc_clock_ConvertToStream(vlc_clock_t * clock, vlc_tick_t system)
return vlc_clock_to_stream(clock, system);
}
-void vlc_clock_SetDejitter(vlc_clock_t * clock, vlc_tick_t delay, int cr_avg)
-{
- clock->set_dejitter(clock, delay, cr_avg);
-}
-
-vlc_tick_t vlc_clock_GetDejitter(vlc_clock_t * clock)
+void vlc_clock_SetDejitter(vlc_clock_t * clock, vlc_tick_t delay)
{
- return vlc_clock_get_dejitter(clock);
+ clock->set_dejitter(clock, delay);
}
static void vlc_clock_set_master_cbk(vlc_clock_t * clk)
diff --git a/src/clock/clock.h b/src/clock/clock.h
index e079440af6..b63cccca82 100644
--- a/src/clock/clock.h
+++ b/src/clock/clock.h
@@ -51,6 +51,10 @@ void vlc_clock_main_Abort(vlc_clock_main_t * main);
*/
void vlc_clock_main_Reset(vlc_clock_main_t * main);
+void vlc_clock_main_SetFirstPcr(vlc_clock_main_t * main, vlc_tick_t system_now,
+ vlc_tick_t pts);
+void vlc_clock_main_SetInputDejitter(vlc_clock_main_t * main, vlc_tick_t delay);
+
/**
* This function set the allocated interface as the master making the current
* master if any a slave.
@@ -126,9 +130,9 @@ vlc_tick_t vlc_clock_ConvertToStream(vlc_clock_t * clock, vlc_tick_t system);
/**
* This function sets the dejitter delay to absorb the clock jitter
- * also used as the ma1ximum delay before the synchro is considered to kick in
+ * also used as the maximum delay before the synchro is considered to kick in
*/
-void vlc_clock_SetDejitter(vlc_clock_t * clock, vlc_tick_t delay, int cr_avg);
+void vlc_clock_SetDejitter(vlc_clock_t * clock, vlc_tick_t delay);
/**
* This function retrieves the synchronization delay
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 5d8be99f9f..b6a956285d 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -820,12 +820,19 @@ static void EsOutDecodersStopBuffering( es_out_t *out, bool b_forced )
/* Here is a good place to destroy unused vout with every demuxer */
input_resource_TerminateVout( input_priv(p_sys->p_input)->p_resource );
+
/* */
const vlc_tick_t i_wakeup_delay = VLC_TICK_FROM_MS(10); /* FIXME CLEANUP thread wake up time*/
const vlc_tick_t i_current_date = p_sys->b_paused ? p_sys->i_pause_date : vlc_tick_now();
- input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_input_clock, true,
- i_current_date + i_wakeup_delay - i_buffering_duration );
+ const vlc_tick_t update = i_current_date + i_wakeup_delay - i_buffering_duration;
+
+ /* Send the first PCR to the output clock. This will be used as a reference
+ * point for the sync point. */
+ vlc_clock_main_SetFirstPcr(p_sys->p_pgrm->p_main_clock, update,
+ i_stream_start);
+
+ input_clock_ChangeSystemOrigin( p_sys->p_pgrm->p_input_clock, true, update );
foreach_es_then_es_slaves(p_es)
{
@@ -1154,6 +1161,7 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
if( p_sys->b_paused )
input_clock_ChangePause( p_pgrm->p_input_clock, p_sys->b_paused, p_sys->i_pause_date );
input_clock_SetJitter( p_pgrm->p_input_clock, p_sys->i_pts_delay, p_sys->i_cr_average );
+ vlc_clock_main_SetInputDejitter( p_pgrm->p_main_clock, p_sys->i_pts_delay );
/* Append it */
vlc_list_append(&p_pgrm->node, &p_sys->programs);
@@ -3061,9 +3069,15 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
p_sys->i_cr_average = i_cr_average;
if (b_change_clock)
+ {
vlc_list_foreach(pgrm, &p_sys->programs, node)
- input_clock_SetJitter(pgrm->p_input_clock, i_pts_delay
- + i_pts_jitter, i_cr_average);
+ {
+ input_clock_SetJitter(pgrm->p_input_clock, i_pts_delay
+ + i_pts_jitter, i_cr_average);
+ vlc_clock_main_SetInputDejitter(pgrm->p_main_clock,
+ i_pts_delay + i_pts_jitter);
+ }
+ }
return VLC_SUCCESS;
}
--
2.20.1
More information about the vlc-devel
mailing list