[vlc-devel] [PATCH 14/18] core: switch to the new output clock
Thomas Guillem
thomas at gllm.fr
Thu Mar 7 15:25:36 CET 2019
Co-authored-by: Denis Charmet <typx at videolan.org>
Co-authored-by: RĂ©mi Denis-Courmont <remi at remlab.net>
---
src/input/decoder.c | 219 ++++++++++++++++++--------------------------
src/input/decoder.h | 2 +-
src/input/es_out.c | 69 +++++++++++---
3 files changed, 146 insertions(+), 144 deletions(-)
diff --git a/src/input/decoder.c b/src/input/decoder.c
index a3b55d85fe..cf7fd43995 100644
--- a/src/input/decoder.c
+++ b/src/input/decoder.c
@@ -1,7 +1,7 @@
/*****************************************************************************
* decoder.c: Functions for the management of decoders
*****************************************************************************
- * Copyright (C) 1999-2004 VLC authors and VideoLAN
+ * Copyright (C) 1999-2019 VLC authors, VideoLAN and Videolabs SAS
*
* Authors: Christophe Massiot <massiot at via.ecp.fr>
* Gildas Bazin <gbazin at videolan.org>
@@ -45,7 +45,7 @@
#include "audio_output/aout_internal.h"
#include "stream_output/stream_output.h"
#include "input_internal.h"
-#include "../clock/input_clock.h"
+#include "../clock/clock.h"
#include "decoder.h"
#include "event.h"
#include "resource.h"
@@ -67,8 +67,7 @@ struct decoder_owner
decoder_t dec;
input_thread_t *p_input;
input_resource_t*p_resource;
- input_clock_t *p_clock;
- float last_rate;
+ vlc_clock_t *p_clock;
int i_spu_channel;
int64_t i_spu_order;
@@ -100,7 +99,6 @@ struct decoder_owner
vlc_cond_t wait_request;
vlc_cond_t wait_acknowledge;
vlc_cond_t wait_fifo; /* TODO: merge with wait_acknowledge */
- vlc_cond_t wait_timed;
/* -- These variables need locking on write(only) -- */
audio_output_t *p_aout;
@@ -113,7 +111,8 @@ struct decoder_owner
/* Pause & Rate */
bool reset_out_state;
vlc_tick_t pause_date;
- float rate;
+ vlc_tick_t delay;
+ float request_rate, output_rate;
unsigned frames_countdown;
bool paused;
@@ -141,9 +140,6 @@ struct decoder_owner
sout_packetizer_input_t *p_sout_input;
} cc;
- /* Delay */
- vlc_tick_t i_ts_delay;
-
/* Mouse event */
vlc_mutex_t mouse_lock;
vlc_mouse_event mouse_event;
@@ -345,7 +341,7 @@ static int aout_update_format( decoder_t *p_dec )
if( p_dec->fmt_out.i_codec == VLC_CODEC_DTS )
var_SetBool( p_aout, "dtshd", p_dec->fmt_out.i_profile > 0 );
- if( aout_DecNew( p_aout, &format, NULL,
+ if( aout_DecNew( p_aout, &format, p_owner->p_clock,
&p_dec->fmt_out.audio_replay_gain ) )
{
input_resource_PutAout( p_owner->p_resource, p_aout );
@@ -540,7 +536,7 @@ static int vout_update_format( decoder_t *p_dec )
}
p_vout = input_resource_GetVout( p_owner->p_resource,
&(vout_configuration_t) {
- .vout = p_vout, .fmt = &fmt,
+ .vout = p_vout, .clock = p_owner->p_clock, .fmt = &fmt,
.dpb_size = dpb_size + p_dec->i_extra_picture_buffers + 1,
.mouse_event = MouseEvent, .mouse_opaque = p_dec
} );
@@ -607,6 +603,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
if( p_owner->p_vout )
{
vlc_mutex_lock( &p_owner->lock );
+ vout_SetSubpictureClock(p_owner->p_vout, NULL);
vout_Release(p_owner->p_vout);
p_owner->p_vout = NULL;
vlc_mutex_unlock( &p_owner->lock );
@@ -621,9 +618,14 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
vlc_mutex_lock( &p_owner->lock );
if( p_owner->p_vout )
+ {
+ vout_SetSubpictureClock(p_owner->p_vout, NULL);
vout_Release(p_owner->p_vout);
+ }
p_owner->p_vout = p_vout;
vlc_mutex_unlock( &p_owner->lock );
+
+ vout_SetSubpictureClock( p_vout, p_owner->p_clock );
}
else
vout_Release(p_vout);
@@ -656,24 +658,21 @@ static int DecoderGetInputAttachments( decoder_t *p_dec,
return VLC_SUCCESS;
}
-static vlc_tick_t DecoderGetDisplayDate( decoder_t *p_dec, vlc_tick_t i_ts )
+static vlc_tick_t DecoderGetDisplayDate( decoder_t *p_dec, vlc_tick_t system_now,
+ vlc_tick_t i_ts )
{
struct decoder_owner *p_owner = dec_get_owner( p_dec );
vlc_mutex_lock( &p_owner->lock );
if( p_owner->b_waiting || p_owner->paused )
i_ts = VLC_TICK_INVALID;
+ float rate = p_owner->output_rate;
vlc_mutex_unlock( &p_owner->lock );
if( !p_owner->p_clock || i_ts == VLC_TICK_INVALID )
return i_ts;
- if( input_clock_ConvertTS( VLC_OBJECT(p_dec), p_owner->p_clock, NULL, &i_ts, NULL, INT64_MAX ) ) {
- msg_Err(p_dec, "Could not get display date for timestamp %"PRId64"", i_ts);
- return VLC_TICK_INVALID;
- }
-
- return i_ts;
+ return vlc_clock_ConvertToSystem( p_owner->p_clock, system_now, i_ts, rate );
}
static float DecoderGetDisplayRate( decoder_t *p_dec )
@@ -682,7 +681,10 @@ static float DecoderGetDisplayRate( decoder_t *p_dec )
if( !p_owner->p_clock )
return 1.f;
- return input_clock_GetRate( p_owner->p_clock );
+ vlc_mutex_lock( &p_owner->lock );
+ float rate = p_owner->output_rate;
+ vlc_mutex_unlock( &p_owner->lock );
+ return rate;
}
/*****************************************************************************
@@ -736,24 +738,6 @@ static void DecoderWaitUnblock( decoder_t *p_dec )
}
}
-/* DecoderTimedWait: Interruptible wait
- * Returns VLC_SUCCESS if wait was not interrupted, and VLC_EGENERIC otherwise */
-static int DecoderTimedWait( decoder_t *p_dec, vlc_tick_t deadline )
-{
- struct decoder_owner *p_owner = dec_get_owner( p_dec );
-
- if (deadline <= vlc_tick_now())
- return VLC_SUCCESS;
-
- vlc_fifo_Lock( p_owner->p_fifo );
- while( !p_owner->flushing
- && vlc_fifo_TimedWaitCond( p_owner->p_fifo, &p_owner->wait_timed,
- deadline ) == 0 );
- int ret = p_owner->flushing ? VLC_EGENERIC : VLC_SUCCESS;
- vlc_fifo_Unlock( p_owner->p_fifo );
- return ret;
-}
-
static inline void DecoderUpdatePreroll( vlc_tick_t *pi_preroll, const block_t *p )
{
if( p->i_flags & BLOCK_FLAG_PREROLL )
@@ -768,55 +752,6 @@ static inline void DecoderUpdatePreroll( vlc_tick_t *pi_preroll, const block_t *
*pi_preroll = __MIN( *pi_preroll, p->i_pts );
}
-static void DecoderFixTs( decoder_t *p_dec, vlc_tick_t *pi_ts0, vlc_tick_t *pi_ts1,
- vlc_tick_t *pi_duration, float *p_rate, vlc_tick_t i_ts_bound )
-{
- struct decoder_owner *p_owner = dec_get_owner( p_dec );
- input_clock_t *p_clock = p_owner->p_clock;
-
- vlc_mutex_assert( &p_owner->lock );
-
- const vlc_tick_t i_es_delay = p_owner->i_ts_delay;
-
- if( !p_clock )
- return;
-
- const bool b_ephemere = pi_ts1 && *pi_ts0 == *pi_ts1;
- float rate = 1.f;
-
- if( *pi_ts0 != VLC_TICK_INVALID )
- {
- *pi_ts0 += i_es_delay;
- if( pi_ts1 && *pi_ts1 != VLC_TICK_INVALID )
- *pi_ts1 += i_es_delay;
- if( i_ts_bound != INT64_MAX )
- i_ts_bound += i_es_delay;
- if( input_clock_ConvertTS( VLC_OBJECT(p_dec), p_clock, &rate, pi_ts0, pi_ts1, i_ts_bound ) ) {
- const char *psz_name = module_get_name( p_dec->p_module, false );
- if( pi_ts1 != NULL )
- msg_Err(p_dec, "Could not convert timestamps %"PRId64
- ", %"PRId64" for %s", *pi_ts0, *pi_ts1, psz_name );
- else
- msg_Err(p_dec, "Could not convert timestamp %"PRId64" for %s", *pi_ts0, psz_name );
- *pi_ts0 = VLC_TICK_INVALID;
- }
- }
- else
- {
- rate = input_clock_GetRate( p_clock );
- }
-
- /* Do not create ephemere data because of rounding errors */
- if( !b_ephemere && pi_ts1 && *pi_ts1 != VLC_TICK_INVALID && *pi_ts0 == *pi_ts1 )
- *pi_ts1 += 1;
-
- if( pi_duration )
- *pi_duration = ( *pi_duration / rate ) + 0.999f;
-
- if( p_rate )
- *p_rate = rate;
-}
-
#ifdef ENABLE_SOUT
static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
{
@@ -834,8 +769,6 @@ static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
}
DecoderWaitUnblock( p_dec );
- DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
- &p_sout_block->i_length, NULL, INT64_MAX );
vlc_mutex_unlock( &p_owner->lock );
@@ -1068,9 +1001,6 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
}
const bool b_dated = p_picture->date != VLC_TICK_INVALID;
- float rate = 1.f;
- DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
- &rate, DECODER_BOGUS_VIDEO_DELAY );
vlc_mutex_unlock( &p_owner->lock );
@@ -1088,13 +1018,7 @@ static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
if( p_picture->b_force || p_picture->date != VLC_TICK_INVALID )
/* FIXME: VLC_TICK_INVALID -- verify video_output */
{
- if( rate != p_owner->last_rate || b_first_after_wait )
- {
- /* Be sure to not display old picture after our own */
- vout_Flush( p_vout, p_picture->date );
- p_owner->last_rate = rate;
- }
- else if( p_picture->b_still )
+ if( p_picture->b_still )
{
/* Ensure no earlier higher pts breaks still state */
vout_Flush( p_vout, p_picture->date );
@@ -1235,19 +1159,12 @@ static void DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
}
/* */
- float rate = 1.f;
-
DecoderWaitUnblock( p_dec );
- DecoderFixTs( p_dec, &p_audio->i_pts, NULL, &p_audio->i_length,
- &rate, AOUT_MAX_ADVANCE_TIME );
vlc_mutex_unlock( &p_owner->lock );
audio_output_t *p_aout = p_owner->p_aout;
- if( p_aout != NULL && p_audio->i_pts != VLC_TICK_INVALID
- && rate >= 1 / (float) AOUT_MAX_INPUT_RATE
- && rate <= AOUT_MAX_INPUT_RATE
- && !DecoderTimedWait( p_dec, p_audio->i_pts - AOUT_MAX_PREPARE_TIME ) )
+ if( p_aout != NULL && p_audio->i_pts != VLC_TICK_INVALID )
{
int status = aout_DecPlay( p_aout, p_audio );
if( status == AOUT_DEC_CHANGED )
@@ -1336,12 +1253,9 @@ static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic )
}
DecoderWaitUnblock( p_dec );
- DecoderFixTs( p_dec, &p_subpic->i_start, &p_subpic->i_stop, NULL,
- NULL, INT64_MAX );
vlc_mutex_unlock( &p_owner->lock );
- if( p_subpic->i_start == VLC_TICK_INVALID
- || DecoderTimedWait( p_dec, p_subpic->i_start - SPU_MAX_PREPARE_TIME ) )
+ if( p_subpic->i_start == VLC_TICK_INVALID )
{
subpicture_Delete( p_subpic );
return;
@@ -1598,12 +1512,42 @@ static void OutputChangeRate( decoder_t *p_dec, float rate )
switch( p_dec->fmt_out.i_cat )
{
case VIDEO_ES:
+ if( p_owner->p_vout != NULL )
+ vout_ChangeRate( p_owner->p_vout, rate );
break;
case AUDIO_ES:
if( p_owner->p_aout != NULL )
aout_DecChangeRate( p_owner->p_aout, rate );
break;
case SPU_ES:
+ if( p_owner->p_vout != NULL )
+ vout_ChangeSpuRate( p_owner->p_vout, rate );
+ break;
+ default:
+ vlc_assert_unreachable();
+ }
+ p_owner->output_rate = rate;
+}
+
+static void OutputChangeDelay( decoder_t *p_dec, vlc_tick_t delay )
+{
+ struct decoder_owner *p_owner = dec_get_owner( p_dec );
+
+ msg_Dbg( p_dec, "changing delay: %"PRId64, delay );
+
+ switch( p_dec->fmt_out.i_cat )
+ {
+ case VIDEO_ES:
+ if( p_owner->p_vout != NULL )
+ vout_ChangeDelay( p_owner->p_vout, delay );
+ break;
+ case AUDIO_ES:
+ if( p_owner->p_aout != NULL )
+ aout_DecChangeDelay( p_owner->p_aout, delay );
+ break;
+ case SPU_ES:
+ if( p_owner->p_vout != NULL )
+ vout_ChangeSpuDelay( p_owner->p_vout, delay );
break;
default:
vlc_assert_unreachable();
@@ -1620,6 +1564,7 @@ static void *DecoderThread( void *p_data )
decoder_t *p_dec = (decoder_t *)p_data;
struct decoder_owner *p_owner = dec_get_owner( p_dec );
float rate = 1.f;
+ vlc_tick_t delay = 0;
bool paused = false;
/* The decoder's main loop */
@@ -1656,6 +1601,7 @@ static void *DecoderThread( void *p_data )
{
rate = 1.f;
paused = false;
+ delay = 0;
p_owner->reset_out_state = false;
}
@@ -1676,11 +1622,11 @@ static void *DecoderThread( void *p_data )
continue;
}
- if( rate != p_owner->rate )
+ if( rate != p_owner->request_rate )
{
int canc = vlc_savecancel();
- rate = p_owner->rate;
+ rate = p_owner->request_rate;
vlc_fifo_Unlock( p_owner->p_fifo );
vlc_mutex_lock( &p_owner->lock );
@@ -1691,6 +1637,21 @@ static void *DecoderThread( void *p_data )
vlc_fifo_Lock( p_owner->p_fifo );
}
+ if( delay != p_owner->delay )
+ {
+ int canc = vlc_savecancel();
+
+ delay = p_owner->delay;
+ vlc_fifo_Unlock( p_owner->p_fifo );
+
+ vlc_mutex_lock( &p_owner->lock );
+ OutputChangeDelay( p_dec, delay );
+ vlc_mutex_unlock( &p_owner->lock );
+
+ vlc_restorecancel( canc );
+ vlc_fifo_Lock( p_owner->p_fifo );
+ }
+
if( p_owner->paused && p_owner->frames_countdown == 0 )
{ /* Wait for resumption from pause */
p_owner->b_idle = true;
@@ -1794,7 +1755,7 @@ static const struct decoder_owner_callbacks dec_spu_cbs =
*/
static decoder_t * CreateDecoder( vlc_object_t *p_parent,
input_thread_t *p_input,
- const es_format_t *fmt,
+ const es_format_t *fmt, vlc_clock_t *p_clock,
input_resource_t *p_resource,
sout_instance_t *p_sout )
{
@@ -1806,8 +1767,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
return NULL;
p_dec = &p_owner->dec;
+ p_owner->p_clock = p_clock;
p_owner->i_preroll_end = (vlc_tick_t)INT64_MIN;
- p_owner->last_rate = 1.f;
p_owner->p_input = p_input;
p_owner->p_resource = p_resource;
p_owner->p_aout = NULL;
@@ -1822,7 +1783,8 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_owner->p_description = NULL;
p_owner->reset_out_state = false;
- p_owner->rate = 1.f;
+ p_owner->delay = 0;
+ p_owner->output_rate = p_owner->request_rate = 1.f;
p_owner->paused = false;
p_owner->pause_date = VLC_TICK_INVALID;
p_owner->frames_countdown = 0;
@@ -1857,7 +1819,6 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
vlc_cond_init( &p_owner->wait_request );
vlc_cond_init( &p_owner->wait_acknowledge );
vlc_cond_init( &p_owner->wait_fifo );
- vlc_cond_init( &p_owner->wait_timed );
/* Load a packetizer module if the input is not already packetized */
if( p_sout == NULL && !fmt->b_packetized )
@@ -1934,7 +1895,6 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
p_owner->cc.pp_decoder[i] = NULL;
p_owner->cc.p_sout_input = NULL;
p_owner->cc.b_sout_created = false;
- p_owner->i_ts_delay = 0;
return p_dec;
}
@@ -1994,6 +1954,7 @@ static void DeleteDecoder( decoder_t * p_dec )
{
vout_FlushSubpictureChannel( p_owner->p_vout,
p_owner->i_spu_channel );
+ vout_SetSubpictureClock(p_owner->p_vout, NULL);
vout_Release(p_owner->p_vout);
}
break;
@@ -2012,7 +1973,6 @@ static void DeleteDecoder( decoder_t * p_dec )
decoder_Destroy( p_owner->p_packetizer );
- vlc_cond_destroy( &p_owner->wait_timed );
vlc_cond_destroy( &p_owner->wait_fifo );
vlc_cond_destroy( &p_owner->wait_acknowledge );
vlc_cond_destroy( &p_owner->wait_request );
@@ -2042,7 +2002,7 @@ static void DecoderUnsupportedCodec( decoder_t *p_dec, const es_format_t *fmt, b
/* TODO: pass p_sout through p_resource? -- Courmisch */
static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
- const es_format_t *fmt, input_clock_t *p_clock,
+ const es_format_t *fmt, vlc_clock_t *p_clock,
input_resource_t *p_resource,
sout_instance_t *p_sout )
{
@@ -2051,7 +2011,7 @@ static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
int i_priority;
/* Create the decoder configuration structure */
- p_dec = CreateDecoder( p_parent, p_input, fmt, p_resource, p_sout );
+ p_dec = CreateDecoder( p_parent, p_input, fmt, p_clock, p_resource, p_sout );
if( p_dec == NULL )
{
msg_Err( p_parent, "could not create %s", psz_type );
@@ -2069,7 +2029,6 @@ static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
}
struct decoder_owner *p_owner = dec_get_owner( p_dec );
- p_owner->p_clock = p_clock;
assert( p_dec->fmt_in.i_cat != UNKNOWN_ES );
if( p_dec->fmt_in.i_cat == AUDIO_ES )
@@ -2112,7 +2071,7 @@ static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
* \return the spawned decoder object
*/
decoder_t *input_DecoderNew( input_thread_t *p_input,
- es_format_t *fmt, input_clock_t *p_clock,
+ es_format_t *fmt, vlc_clock_t *p_clock,
sout_instance_t *p_sout )
{
return decoder_New( VLC_OBJECT(p_input), p_input, fmt, p_clock,
@@ -2143,9 +2102,7 @@ void input_DecoderDelete( decoder_t *p_dec )
vlc_cancel( p_owner->thread );
vlc_fifo_Lock( p_owner->p_fifo );
- /* Signal DecoderTimedWait */
p_owner->flushing = true;
- vlc_cond_signal( &p_owner->wait_timed );
vlc_fifo_Unlock( p_owner->p_fifo );
/* Make sure we aren't waiting/decoding anymore */
@@ -2293,7 +2250,6 @@ void input_DecoderFlush( decoder_t *p_dec )
p_owner->frames_countdown++;
vlc_fifo_Signal( p_owner->p_fifo );
- vlc_cond_signal( &p_owner->wait_timed );
vlc_fifo_Unlock( p_owner->p_fifo );
}
@@ -2420,18 +2376,17 @@ void input_DecoderChangeRate( decoder_t *dec, float rate )
struct decoder_owner *owner = dec_get_owner( dec );
vlc_fifo_Lock( owner->p_fifo );
- owner->rate = rate;
- vlc_fifo_Signal( owner->p_fifo );
+ owner->request_rate = rate;
vlc_fifo_Unlock( owner->p_fifo );
}
-void input_DecoderChangeDelay( decoder_t *p_dec, vlc_tick_t i_delay )
+void input_DecoderChangeDelay( decoder_t *dec, vlc_tick_t delay )
{
- struct decoder_owner *p_owner = dec_get_owner( p_dec );
+ struct decoder_owner *owner = dec_get_owner( dec );
- vlc_mutex_lock( &p_owner->lock );
- p_owner->i_ts_delay = i_delay;
- vlc_mutex_unlock( &p_owner->lock );
+ vlc_fifo_Lock( owner->p_fifo );
+ owner->delay = delay;
+ vlc_fifo_Unlock( owner->p_fifo );
}
void input_DecoderStartWait( decoder_t *p_dec )
diff --git a/src/input/decoder.h b/src/input/decoder.h
index db491ac44e..651bd13d69 100644
--- a/src/input/decoder.h
+++ b/src/input/decoder.h
@@ -28,7 +28,7 @@
#include <vlc_codec.h>
#include <vlc_mouse.h>
-decoder_t *input_DecoderNew( input_thread_t *, es_format_t *, input_clock_t *,
+decoder_t *input_DecoderNew( input_thread_t *, es_format_t *, vlc_clock_t *,
sout_instance_t * ) VLC_USED;
/**
diff --git a/src/input/es_out.c b/src/input/es_out.c
index 511b19a8d4..da5925933b 100644
--- a/src/input/es_out.c
+++ b/src/input/es_out.c
@@ -1,7 +1,7 @@
/*****************************************************************************
* es_out.c: Es Out handler for input.
*****************************************************************************
- * Copyright (C) 2003-2004 VLC authors and VideoLAN
+ * Copyright (C) 2003-2019 VLC authors, VideoLAN and Videolabs SAS
*
* Authors: Laurent Aimar <fenrir at via.ecp.fr>
* Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
@@ -42,6 +42,7 @@
#include "input_internal.h"
#include "../clock/input_clock.h"
+#include "../clock/clock.h"
#include "decoder.h"
#include "es_out.h"
#include "event.h"
@@ -69,7 +70,9 @@ typedef struct
bool b_scrambled;
/* Clock for this program */
- input_clock_t *p_input_clock;
+ input_clock_t *p_input_clock;
+ vlc_clock_main_t *p_main_clock;
+ vlc_clock_t *p_master_clock;
vlc_meta_t *p_meta;
struct vlc_list node;
@@ -113,6 +116,7 @@ struct es_out_id_t
decoder_t *p_dec;
decoder_t *p_dec_record;
+ vlc_clock_t *p_clock;
/* Fields for Video with CC */
struct
@@ -453,6 +457,7 @@ static void EsOutTerminate( es_out_t *out )
vlc_list_foreach(p_pgrm, &p_sys->programs, node)
{
input_clock_Delete( p_pgrm->p_input_clock );
+ vlc_clock_main_Delete( p_pgrm->p_main_clock );
if( p_pgrm->p_meta )
vlc_meta_Delete( p_pgrm->p_meta );
@@ -612,7 +617,7 @@ static int EsOutSetRecord( es_out_t *out, bool b_record )
if( !p_es->p_dec )
continue;
- p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_input_clock, p_sys->p_sout_record );
+ p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, NULL, p_sys->p_sout_record );
if( p_es->p_dec_record && p_sys->b_buffering )
input_DecoderStartWait( p_es->p_dec_record );
}
@@ -710,7 +715,10 @@ static void EsOutChangePosition( es_out_t *out )
es_out_pgrm_t *pgrm;
vlc_list_foreach(pgrm, &p_sys->programs, node)
+ {
input_clock_Reset(pgrm->p_input_clock);
+ vlc_clock_main_Reset(pgrm->p_main_clock);
+ }
p_sys->b_buffering = true;
p_sys->i_buffering_extra_initial = 0;
@@ -792,12 +800,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)
{
@@ -854,7 +869,10 @@ static void EsOutProgramChangePause( es_out_t *out, bool b_paused, vlc_tick_t i_
es_out_pgrm_t *pgrm;
vlc_list_foreach(pgrm, &p_sys->programs, node)
+ {
input_clock_ChangePause(pgrm->p_input_clock, b_paused, i_date);
+ vlc_clock_main_ChangePause(pgrm->p_main_clock, i_date, b_paused);
+ }
}
static void EsOutDecoderChangeDelay( es_out_t *out, es_out_id_t *p_es )
@@ -1111,15 +1129,21 @@ static es_out_pgrm_t *EsOutProgramAdd( es_out_t *out, int i_group )
p_pgrm->b_selected = false;
p_pgrm->b_scrambled = false;
p_pgrm->p_meta = NULL;
+
+ p_pgrm->p_master_clock = NULL;
p_pgrm->p_input_clock = input_clock_New( p_sys->rate );
- if( !p_pgrm->p_input_clock )
+ p_pgrm->p_main_clock = vlc_clock_main_New();
+ if( !p_pgrm->p_input_clock || !p_pgrm->p_main_clock )
{
+ if( p_pgrm->p_input_clock )
+ input_clock_Delete( p_pgrm->p_input_clock );
free( p_pgrm );
return NULL;
}
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);
@@ -1167,6 +1191,7 @@ static int EsOutProgramDel( es_out_t *out, int i_group )
p_sys->p_pgrm = NULL;
input_clock_Delete( p_pgrm->p_input_clock );
+ vlc_clock_main_Delete( p_pgrm->p_main_clock );
if( p_pgrm->p_meta )
vlc_meta_Delete( p_pgrm->p_meta );
@@ -1711,6 +1736,7 @@ static es_out_id_t *EsOutAddSlaveLocked( es_out_t *out, const es_format_t *fmt,
es->psz_title = EsGetTitle(es);
es->p_dec = NULL;
es->p_dec_record = NULL;
+ es->p_clock = NULL;
es->cc.type = 0;
es->cc.i_bitmap = 0;
es->p_master = p_master;
@@ -1769,18 +1795,26 @@ static void EsOutCreateDecoder( es_out_t *out, es_out_id_t *p_es )
input_thread_t *p_input = p_sys->p_input;
decoder_t *dec;
- dec = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_input_clock,
+ if( p_es->fmt.i_cat == AUDIO_ES && p_es->p_pgrm->p_master_clock == NULL )
+ p_es->p_pgrm->p_master_clock = p_es->p_clock =
+ vlc_clock_main_CreateMaster( p_es->p_pgrm->p_main_clock );
+ else
+ p_es->p_clock = vlc_clock_main_CreateSlave( p_es->p_pgrm->p_main_clock );
+ if( !p_es->p_clock )
+ return;
+
+ dec = input_DecoderNew( p_input, &p_es->fmt, p_es->p_clock,
input_priv(p_input)->p_sout );
if( dec != NULL )
{
- input_DecoderChangeRate( dec, 1 / p_sys->rate );
+ input_DecoderChangeRate( dec, p_sys->rate );
if( p_sys->b_buffering )
input_DecoderStartWait( dec );
if( !p_es->p_master && p_sys->p_sout_record )
{
- p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, p_es->p_pgrm->p_input_clock, p_sys->p_sout_record );
+ p_es->p_dec_record = input_DecoderNew( p_input, &p_es->fmt, NULL, p_sys->p_sout_record );
if( p_es->p_dec_record && p_sys->b_buffering )
input_DecoderStartWait( p_es->p_dec_record );
}
@@ -1802,6 +1836,10 @@ static void EsOutDestroyDecoder( es_out_t *out, es_out_id_t *p_es )
input_DecoderDelete( p_es->p_dec );
p_es->p_dec = NULL;
+ if( p_es->p_pgrm->p_master_clock == p_es->p_clock )
+ p_es->p_pgrm->p_master_clock = NULL;
+ vlc_clock_Delete( p_es->p_clock );
+ p_es->p_clock = NULL;
if( p_es->p_dec_record )
{
@@ -2698,7 +2736,10 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
/* reset clock */
vlc_list_foreach(pgrm, &p_sys->programs, node)
+ {
input_clock_Reset(pgrm->p_input_clock);
+ vlc_clock_main_Reset(p_pgrm->p_main_clock);
+ }
}
else
{
@@ -3009,9 +3050,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