[vlc-commits] vout: use vlc_clock_t
Thomas Guillem
git at videolan.org
Mon Mar 11 10:19:03 CET 2019
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Wed Mar 6 18:40:45 2019 +0100| [f2b2de861eec098e60d426d2bdfb448f1047e160] | committer: Thomas Guillem
vout: use vlc_clock_t
During the transition, the clock argument is not mandatory. If the clock is
NULL, the vout will use ts from the picture_t that were converted from the
decoder.
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=f2b2de861eec098e60d426d2bdfb448f1047e160
---
src/clock/clock.c | 72 ++++++++---------
src/clock/clock.h | 12 +--
src/video_output/control.h | 8 ++
src/video_output/video_output.c | 162 +++++++++++++++++++++++++++++++--------
src/video_output/vout_internal.h | 32 ++++++++
5 files changed, 212 insertions(+), 74 deletions(-)
diff --git a/src/clock/clock.c b/src/clock/clock.c
index 3fae6c9161..15a6cf68e4 100644
--- a/src/clock/clock.c
+++ b/src/clock/clock.c
@@ -38,7 +38,7 @@ struct vlc_clock_main_t
/**
* Linear function
- * system = pts * coeff / rate + offset
+ * system = ts * coeff / rate + offset
*/
clock_point_t last;
average_t coeff_avg; /* Moving average to smooth out the instant coeff */
@@ -59,12 +59,12 @@ struct vlc_clock_main_t
struct vlc_clock_t
{
vlc_tick_t (*update)(vlc_clock_t *clock, vlc_tick_t system_now,
- vlc_tick_t pts, double rate);
+ vlc_tick_t ts, double rate);
void (*reset)(vlc_clock_t *clock);
vlc_tick_t (*set_delay)(vlc_clock_t *clock, vlc_tick_t delay);
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, double rate);
+ vlc_tick_t ts, double rate);
vlc_clock_main_t *owner;
vlc_tick_t delay;
@@ -72,12 +72,12 @@ struct vlc_clock_t
};
static vlc_tick_t main_stream_to_system(vlc_clock_main_t *main_clock,
- vlc_tick_t pts)
+ vlc_tick_t ts)
{
if (main_clock->offset == VLC_TICK_INVALID)
return VLC_TICK_INVALID;
return (vlc_tick_t)
- (pts * main_clock->coeff / main_clock->rate + main_clock->offset);
+ (ts * main_clock->coeff / main_clock->rate + main_clock->offset);
}
static void vlc_clock_main_reset(vlc_clock_main_t *main_clock)
@@ -94,21 +94,21 @@ static void vlc_clock_main_reset(vlc_clock_main_t *main_clock)
static vlc_tick_t vlc_clock_master_update(vlc_clock_t *clock,
vlc_tick_t system_now,
- vlc_tick_t pts, double rate)
+ vlc_tick_t ts, double rate)
{
vlc_clock_main_t *main_clock = clock->owner;
- if (unlikely(pts == VLC_TICK_INVALID || system_now == VLC_TICK_INVALID))
+ if (unlikely(ts == VLC_TICK_INVALID || system_now == VLC_TICK_INVALID))
return VLC_TICK_INVALID;
- pts += clock->delay;
+ ts += clock->delay;
vlc_mutex_lock(&main_clock->lock);
- if (main_clock->offset != VLC_TICK_INVALID && pts != main_clock->last.stream)
+ if (main_clock->offset != VLC_TICK_INVALID && ts != main_clock->last.stream)
{
/* We have a reference so we can update coeff */
double instant_coeff = (system_now - main_clock->last.system)
- / (double)(pts - main_clock->last.stream);
+ / (double)(ts - main_clock->last.stream);
if (rate == main_clock->rate)
{
instant_coeff *= rate;
@@ -120,9 +120,9 @@ static vlc_tick_t vlc_clock_master_update(vlc_clock_t *clock,
main_clock->wait_sync_ref =
clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
- main_clock->offset = system_now - pts * main_clock->coeff / rate;
+ main_clock->offset = system_now - ts * main_clock->coeff / rate;
- main_clock->last = clock_point_Create(system_now, pts);
+ main_clock->last = clock_point_Create(system_now, ts);
main_clock->rate = rate;
vlc_cond_broadcast(&main_clock->cond);
@@ -196,7 +196,7 @@ static void vlc_clock_master_set_dejitter(vlc_clock_t *clock, vlc_tick_t delay)
static vlc_tick_t
vlc_clock_monotonic_to_system_locked(vlc_clock_t *clock, vlc_tick_t now,
- vlc_tick_t pts, double rate)
+ vlc_tick_t ts, double rate)
{
vlc_clock_main_t *main_clock = clock->owner;
@@ -208,7 +208,7 @@ vlc_clock_monotonic_to_system_locked(vlc_clock_t *clock, vlc_tick_t now,
* - first PCR). */
const vlc_tick_t pcr_delay =
main_clock->first_pcr.system == VLC_TICK_INVALID ? 0 :
- (pts - main_clock->first_pcr.stream) / rate +
+ (ts - main_clock->first_pcr.stream) / rate +
main_clock->first_pcr.system - now;
const vlc_tick_t input_delay = main_clock->input_dejitter + pcr_delay;
@@ -216,26 +216,26 @@ vlc_clock_monotonic_to_system_locked(vlc_clock_t *clock, vlc_tick_t now,
const vlc_tick_t delay =
__MAX(input_delay, main_clock->output_dejitter);
- main_clock->wait_sync_ref = clock_point_Create(now + delay, pts);
+ main_clock->wait_sync_ref = clock_point_Create(now + delay, ts);
}
- return (pts - main_clock->wait_sync_ref.stream) / rate
+ return (ts - main_clock->wait_sync_ref.stream) / rate
+ main_clock->wait_sync_ref.system;
}
static vlc_tick_t vlc_clock_slave_to_system_locked(vlc_clock_t *clock,
vlc_tick_t now,
- vlc_tick_t pts, double rate)
+ vlc_tick_t ts, double rate)
{
vlc_clock_main_t *main_clock = clock->owner;
if (main_clock->pause_date != VLC_TICK_INVALID)
return INT64_MAX;
- vlc_tick_t system = main_stream_to_system(main_clock, pts);
+ vlc_tick_t system = main_stream_to_system(main_clock, ts);
if (system == VLC_TICK_INVALID)
{
/* We don't have a master sync point, let's fallback to a monotonic ref
* point */
- system = vlc_clock_monotonic_to_system_locked(clock, now, pts, rate);
+ system = vlc_clock_monotonic_to_system_locked(clock, now, ts, rate);
}
return system + (clock->delay - main_clock->delay) * rate;
@@ -243,15 +243,15 @@ static vlc_tick_t vlc_clock_slave_to_system_locked(vlc_clock_t *clock,
static vlc_tick_t vlc_clock_master_to_system_locked(vlc_clock_t *clock,
vlc_tick_t now,
- vlc_tick_t pts, double rate)
+ vlc_tick_t ts, double rate)
{
vlc_clock_main_t *main_clock = clock->owner;
- vlc_tick_t system = main_stream_to_system(main_clock, pts);
+ vlc_tick_t system = main_stream_to_system(main_clock, ts);
if (system == VLC_TICK_INVALID)
{
/* We don't have a master sync point, let's fallback to a monotonic ref
* point */
- system = vlc_clock_monotonic_to_system_locked(clock, now, pts, rate);
+ system = vlc_clock_monotonic_to_system_locked(clock, now, ts, rate);
}
return system + clock->delay * rate;
@@ -259,12 +259,12 @@ static vlc_tick_t vlc_clock_master_to_system_locked(vlc_clock_t *clock,
static vlc_tick_t vlc_clock_slave_update(vlc_clock_t *clock,
vlc_tick_t system_now,
- vlc_tick_t pts, double rate)
+ vlc_tick_t ts, double rate)
{
vlc_clock_main_t *main_clock = clock->owner;
vlc_mutex_lock(&main_clock->lock);
- vlc_tick_t computed = clock->to_system_locked(clock, system_now, pts, rate);
+ vlc_tick_t computed = clock->to_system_locked(clock, system_now, ts, rate);
vlc_mutex_unlock(&main_clock->lock);
return computed != INT64_MAX ? computed - system_now : VLC_TICK_INVALID;
}
@@ -290,7 +290,7 @@ static vlc_tick_t vlc_clock_slave_set_delay(vlc_clock_t *clock, vlc_tick_t delay
return 0;
}
-int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t pts,
+int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t ts,
double rate, vlc_tick_t max_duration)
{
vlc_clock_main_t *main_clock = clock->owner;
@@ -303,7 +303,7 @@ int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t pts,
if (main_clock->pause_date != VLC_TICK_INVALID)
deadline = INT64_MAX;
else
- deadline = clock->to_system_locked(clock, system_now, pts, rate);
+ deadline = clock->to_system_locked(clock, system_now, ts, rate);
deadline = __MIN(deadline, max_deadline);
if (vlc_cond_timedwait(&main_clock->cond, &main_clock->lock, deadline))
@@ -374,12 +374,12 @@ void vlc_clock_main_Reset(vlc_clock_main_t *main_clock)
}
void vlc_clock_main_SetFirstPcr(vlc_clock_main_t *main_clock,
- vlc_tick_t system_now, vlc_tick_t pts)
+ vlc_tick_t system_now, vlc_tick_t ts)
{
vlc_mutex_lock(&main_clock->lock);
if (main_clock->first_pcr.system == VLC_TICK_INVALID)
{
- main_clock->first_pcr = clock_point_Create(system_now, pts);
+ main_clock->first_pcr = clock_point_Create(system_now, ts);
main_clock->wait_sync_ref =
clock_point_Create(VLC_TICK_INVALID, VLC_TICK_INVALID);
}
@@ -433,9 +433,9 @@ void vlc_clock_main_Delete(vlc_clock_main_t *main_clock)
}
vlc_tick_t vlc_clock_Update(vlc_clock_t *clock, vlc_tick_t system_now,
- vlc_tick_t pts, double rate)
+ vlc_tick_t ts, double rate)
{
- return clock->update(clock, system_now, pts, rate);
+ return clock->update(clock, system_now, ts, rate);
}
void vlc_clock_Reset(vlc_clock_t *clock)
@@ -449,24 +449,24 @@ vlc_tick_t vlc_clock_SetDelay(vlc_clock_t *clock, vlc_tick_t delay)
}
vlc_tick_t vlc_clock_ConvertToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
- vlc_tick_t pts, double rate)
+ vlc_tick_t ts, double rate)
{
vlc_clock_main_t *main_clock = clock->owner;
vlc_mutex_lock(&main_clock->lock);
- vlc_tick_t system = clock->to_system_locked(clock, system_now, pts, rate);
+ vlc_tick_t system = clock->to_system_locked(clock, system_now, ts, rate);
vlc_mutex_unlock(&main_clock->lock);
return system;
}
void vlc_clock_ConvertArrayToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
- vlc_tick_t *pts_array, size_t pts_count,
+ vlc_tick_t *ts_array, size_t ts_count,
double rate)
{
vlc_clock_main_t *main_clock = clock->owner;
vlc_mutex_lock(&main_clock->lock);
- for (size_t i = 0; i < pts_count; ++i)
- pts_array[i] = clock->to_system_locked(clock, system_now, pts_array[i],
- rate);
+ for (size_t i = 0; i < ts_count; ++i)
+ ts_array[i] = clock->to_system_locked(clock, system_now, ts_array[i],
+ rate);
vlc_mutex_unlock(&main_clock->lock);
}
diff --git a/src/clock/clock.h b/src/clock/clock.h
index 0088d89ebe..2261c6caa5 100644
--- a/src/clock/clock.h
+++ b/src/clock/clock.h
@@ -44,7 +44,7 @@ void vlc_clock_main_Abort(vlc_clock_main_t *main_clock);
void vlc_clock_main_Reset(vlc_clock_main_t *main_clock);
void vlc_clock_main_SetFirstPcr(vlc_clock_main_t *main_clock,
- vlc_tick_t system_now, vlc_tick_t pts);
+ vlc_tick_t system_now, vlc_tick_t ts);
void vlc_clock_main_SetInputDejitter(vlc_clock_main_t *main_clock,
vlc_tick_t delay);
@@ -90,7 +90,7 @@ void vlc_clock_Delete(vlc_clock_t *clock);
* This function will update the clock drift and returns the drift
*/
vlc_tick_t vlc_clock_Update(vlc_clock_t *clock, vlc_tick_t system_now,
- vlc_tick_t pts, double rate);
+ vlc_tick_t ts, double rate);
/**
* This function resets the clock drift
@@ -103,25 +103,25 @@ void vlc_clock_Reset(vlc_clock_t *clock);
* It returns the amount of time the clock owner need to wait in order to reach
* the time introduced by the new positive delay.
*/
-vlc_tick_t vlc_clock_SetDelay(vlc_clock_t *clock, vlc_tick_t pts_delay);
+vlc_tick_t vlc_clock_SetDelay(vlc_clock_t *clock, vlc_tick_t ts_delay);
/**
* Wait for a timestamp expressed in stream time
*/
-int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t pts,
+int vlc_clock_Wait(vlc_clock_t *clock, vlc_tick_t system_now, vlc_tick_t ts,
double rate, vlc_tick_t max_duration);
/**
* This function converts a timestamp from stream to system
*/
vlc_tick_t vlc_clock_ConvertToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
- vlc_tick_t pts, double rate);
+ vlc_tick_t ts, double rate);
/**
* This functon converts an array of timestamp from stream to system
*/
void vlc_clock_ConvertArrayToSystem(vlc_clock_t *clock, vlc_tick_t system_now,
- vlc_tick_t *pts_array, size_t pts_count,
+ vlc_tick_t *ts_array, size_t ts_count,
double rate);
/**
diff --git a/src/video_output/control.h b/src/video_output/control.h
index 9eb7ac32e3..46b78122e4 100644
--- a/src/video_output/control.h
+++ b/src/video_output/control.h
@@ -71,6 +71,14 @@ typedef struct {
unsigned width;
unsigned height;
} window;
+ struct {
+ int channel;
+ float value;
+ } spu_rate;
+ struct {
+ int channel;
+ vlc_tick_t value;
+ } spu_delay;
vlc_mouse_t mouse;
vlc_viewpoint_t viewpoint;
};
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 7aac04be46..3d75b15961 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -5,7 +5,7 @@
* It includes functions allowing to open a new thread, send pictures to a
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
- * Copyright (C) 2000-2007 VLC authors and VideoLAN
+ * Copyright (C) 2000-2019 VLC authors, VideoLAN and Videolabs SAS
*
* Authors: Vincent Seguin <seguin at via.ecp.fr>
* Gildas Bazin <gbazin at videolan.org>
@@ -55,6 +55,7 @@
#include "snapshot.h"
#include "window.h"
#include "../misc/variables.h"
+#include "../clock/clock.h"
/* Maximum delay between 2 displayed pictures.
* XXX it is needed for now but should be removed in the long term.
@@ -268,6 +269,14 @@ int vout_RegisterSubpictureChannel( vout_thread_t *vout )
return channel;
}
+void vout_SetSubpictureClock( vout_thread_t *vout, vlc_clock_t *clock )
+{
+ vlc_mutex_lock(&vout->p->spu_lock);
+ if (vout->p->spu)
+ spu_clock_Set(vout->p->spu, clock);
+ vlc_mutex_unlock(&vout->p->spu_lock);
+}
+
void vout_FlushSubpictureChannel( vout_thread_t *vout, int channel )
{
vout_thread_sys_t *sys = vout->p;
@@ -818,6 +827,7 @@ static void ThreadChangeFilters(vout_thread_t *vout,
static int ThreadDisplayPreparePicture(vout_thread_t *vout, bool reuse, bool frame_by_frame)
{
bool is_late_dropped = vout->p->is_late_dropped && !vout->p->pause.is_on && !frame_by_frame;
+ vout_thread_sys_t *sys = vout->p;
vlc_mutex_lock(&vout->p->filter.lock);
@@ -830,15 +840,19 @@ static int ThreadDisplayPreparePicture(vout_thread_t *vout, bool reuse, bool fra
decoded = picture_Hold(vout->p->displayed.decoded);
} else {
decoded = picture_fifo_Pop(vout->p->decoder_fifo);
+
if (decoded) {
if (is_late_dropped && !decoded->b_force) {
+ const vlc_tick_t date = vlc_tick_now();
+ const vlc_tick_t system_pts = !vout->p->clock ? decoded->date :
+ vlc_clock_ConvertToSystem(vout->p->clock, date,
+ decoded->date, sys->rate);
+ const vlc_tick_t late = date - system_pts;
vlc_tick_t late_threshold;
if (decoded->format.i_frame_rate && decoded->format.i_frame_rate_base)
late_threshold = VLC_TICK_FROM_MS(500) * decoded->format.i_frame_rate_base / decoded->format.i_frame_rate;
else
late_threshold = VOUT_DISPLAY_LATE_THRESHOLD;
- const vlc_tick_t predicted = vlc_tick_now() + 0; /* TODO improve */
- const vlc_tick_t late = predicted - decoded->date;
if (late > late_threshold) {
msg_Warn(vout, "picture is too late to be displayed (missing %"PRId64" ms)", MS_FROM_VLC_TICK(late));
picture_Release(decoded);
@@ -958,12 +972,15 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
* Get the subpicture to be displayed
*/
const bool do_snapshot = vout_snapshot_IsRequested(sys->snapshot);
+ vlc_tick_t system_now = vlc_tick_now();
vlc_tick_t render_subtitle_date;
if (sys->pause.is_on)
render_subtitle_date = sys->pause.date;
else
- render_subtitle_date = filtered->date > 1 ? filtered->date : vlc_tick_now();
- vlc_tick_t system_now = vlc_tick_now();
+ render_subtitle_date = filtered->date <= 1 ? system_now :
+ !sys->clock ? filtered->date :
+ vlc_clock_ConvertToSystem(sys->clock, system_now, filtered->date,
+ sys->rate);
/*
* Get the subpicture to be displayed
@@ -1025,9 +1042,8 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
subpicture_t *subpic = spu_Render(sys->spu,
subpicture_chromas, &fmt_spu_rot,
&vd->source, system_now,
- render_subtitle_date,
- 1.f, do_snapshot,
- vd->info.can_scale_spu);
+ render_subtitle_date, sys->spu_rate,
+ do_snapshot, vd->info.can_scale_spu);
/*
* Perform rendering
*
@@ -1089,8 +1105,13 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
if (!do_dr_spu && sys->spu_blend != NULL && subpic != NULL)
picture_BlendSubpicture(todisplay, sys->spu_blend, subpic);
+ system_now = vlc_tick_now();
+ const vlc_tick_t pts = todisplay->date;
+ const vlc_tick_t system_pts = !sys->clock ? pts :
+ vlc_clock_ConvertToSystem(sys->clock, system_now, pts, sys->rate);
+
if (vd->prepare != NULL)
- vd->prepare(vd, todisplay, do_dr_spu ? subpic : NULL, todisplay->date);
+ vd->prepare(vd, todisplay, do_dr_spu ? subpic : NULL, system_pts);
vout_chrono_Stop(&sys->render);
#if 0
@@ -1102,21 +1123,33 @@ static int ThreadDisplayRenderPicture(vout_thread_t *vout, bool is_forced)
}
#endif
- /* Wait the real date (for rendering jitter) */
-#if 0
- vlc_tick_t delay = todisplay->date - vlc_tick_now();
- if (delay < 1000)
- msg_Warn(vout, "picture is late (%"PRId64" ms)", delay / 1000);
-#endif
if (!is_forced)
- vlc_tick_wait(todisplay->date);
+ {
+ if (sys->clock)
+ {
+ system_now = vlc_tick_now();
+ vlc_clock_Wait(sys->clock, system_now, pts, sys->rate,
+ VOUT_REDISPLAY_DELAY);
+ }
+ else
+ vlc_tick_wait(pts);
+ }
/* Display the direct buffer returned by vout_RenderPicture */
- sys->displayed.date = vlc_tick_now();
vout_display_Display(vd, todisplay);
if (subpic)
subpicture_Delete(subpic);
+ if (!is_forced && sys->clock)
+ {
+ system_now = vlc_tick_now();
+ const vlc_tick_t drift = vlc_clock_Update(sys->clock, system_now,
+ pts, sys->rate);
+ if (drift != VLC_TICK_INVALID)
+ system_now += drift;
+ }
+ sys->displayed.date = system_now;
+
vout_statistic_AddDisplayed(&sys->statistic, 1);
return VLC_SUCCESS;
@@ -1137,14 +1170,19 @@ static int ThreadDisplayPicture(vout_thread_t *vout, vlc_tick_t *deadline)
while (!sys->displayed.next && !ThreadDisplayPreparePicture(vout, false, frame_by_frame))
;
- const vlc_tick_t date = vlc_tick_now();
+ const vlc_tick_t system_now = vlc_tick_now();
const vlc_tick_t render_delay = vout_chrono_GetHigh(&sys->render) + VOUT_MWAIT_TOLERANCE;
bool drop_next_frame = frame_by_frame;
vlc_tick_t date_next = VLC_TICK_INVALID;
+
if (!paused && sys->displayed.next) {
- date_next = sys->displayed.next->date - render_delay;
- if (date_next /* + 0 FIXME */ <= date)
+ const vlc_tick_t next_system_pts = !sys->clock ? sys->displayed.next->date :
+ vlc_clock_ConvertToSystem(sys->clock, system_now,
+ sys->displayed.next->date, sys->rate);
+
+ date_next = next_system_pts - render_delay;
+ if (date_next <= system_now)
drop_next_frame = true;
}
@@ -1162,7 +1200,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout, vlc_tick_t *deadline)
vlc_tick_t date_refresh = VLC_TICK_INVALID;
if (sys->displayed.date != VLC_TICK_INVALID) {
date_refresh = sys->displayed.date + VOUT_REDISPLAY_DELAY - render_delay;
- refresh = date_refresh <= date;
+ refresh = date_refresh <= vlc_tick_now();
}
bool force_refresh = !drop_next_frame && refresh;
@@ -1197,17 +1235,20 @@ void vout_ChangePause(vout_thread_t *vout, bool is_paused, vlc_tick_t date)
assert(!vout->p->pause.is_on || !is_paused);
if (vout->p->pause.is_on) {
- const vlc_tick_t duration = date - vout->p->pause.date;
-
- if (vout->p->step.timestamp != VLC_TICK_INVALID)
- vout->p->step.timestamp += duration;
- if (vout->p->step.last != VLC_TICK_INVALID)
- vout->p->step.last += duration;
- picture_fifo_OffsetDate(vout->p->decoder_fifo, duration);
- if (vout->p->displayed.decoded)
- vout->p->displayed.decoded->date += duration;
- spu_OffsetSubtitleDate(vout->p->spu, duration);
-
+ if (!vout->p->clock)
+ {
+ const vlc_tick_t duration = date - vout->p->pause.date;
+
+ if (vout->p->step.timestamp != VLC_TICK_INVALID)
+ vout->p->step.timestamp += duration;
+ if (vout->p->step.last != VLC_TICK_INVALID)
+ vout->p->step.last += duration;
+ picture_fifo_OffsetDate(vout->p->decoder_fifo, duration);
+ if (vout->p->displayed.decoded)
+ vout->p->displayed.decoded->date += duration;
+ spu_OffsetSubtitleDate(vout->p->spu, duration);
+ }
+
ThreadFilterFlush(vout, false);
} else {
vout->p->step.timestamp = VLC_TICK_INVALID;
@@ -1245,6 +1286,20 @@ static void vout_FlushUnlocked(vout_thread_t *vout, bool below,
picture_fifo_Flush(vout->p->decoder_fifo, date, below);
vout_FilterFlush(vout->p->display);
+
+ if (vout->p->clock)
+ {
+ vlc_clock_Reset(vout->p->clock);
+ vlc_clock_SetDelay(vout->p->clock, vout->p->delay);
+ }
+
+ vlc_mutex_lock(&vout->p->spu_lock);
+ if (vout->p->spu)
+ {
+ spu_clock_Reset(vout->p->spu);
+ spu_clock_SetDelay(vout->p->spu, vout->p->spu_delay);
+ }
+ vlc_mutex_unlock(&vout->p->spu_lock);
}
void vout_Flush(vout_thread_t *vout, vlc_tick_t date)
@@ -1277,6 +1332,42 @@ void vout_NextPicture(vout_thread_t *vout, vlc_tick_t *duration)
vout_control_Release(&vout->p->control);
}
+void vout_ChangeDelay(vout_thread_t *vout, vlc_tick_t delay)
+{
+ vout_thread_sys_t *sys = vout->p;
+
+ vout_control_Hold(&sys->control);
+ if (vout->p->clock)
+ vlc_clock_SetDelay(vout->p->clock, delay);
+ vout->p->delay = delay;
+ vout_control_Release(&sys->control);
+}
+
+void vout_ChangeRate(vout_thread_t *vout, float rate)
+{
+ vout_thread_sys_t *sys = vout->p;
+
+ vout_control_Hold(&sys->control);
+ sys->rate = rate;
+ vout_control_Release(&sys->control);
+}
+
+void vout_ChangeSpuDelay(vout_thread_t *vout, vlc_tick_t delay)
+{
+ vlc_mutex_lock(&vout->p->spu_lock);
+ if (vout->p->spu)
+ spu_clock_SetDelay(vout->p->spu, delay);
+ vout->p->spu_delay = delay;
+ vlc_mutex_unlock(&vout->p->spu_lock);
+}
+
+void vout_ChangeSpuRate(vout_thread_t *vout, float rate)
+{
+ vlc_mutex_lock(&vout->p->spu_lock);
+ vout->p->spu_rate = rate;
+ vlc_mutex_unlock(&vout->p->spu_lock);
+}
+
static void ThreadProcessMouseState(vout_thread_t *vout,
const vlc_mouse_t *win_mouse)
{
@@ -1587,6 +1678,7 @@ static void vout_StopDisplay(vout_thread_t *vout)
spu_Detach(sys->spu);
sys->mouse_event = NULL;
+ sys->clock = NULL;
video_format_Clean(&sys->original);
}
@@ -1788,6 +1880,12 @@ int vout_Request(const vout_configuration_t *cfg, input_thread_t *input)
sys->window_active = true;
} else
vout_UpdateWindowSize(vout);
+
+ sys->delay = sys->spu_delay = 0;
+ sys->rate = sys->spu_rate = 1.f;
+ sys->clock = cfg->clock;
+ sys->delay = sys->spu_delay = 0;
+
vlc_mutex_unlock(&vout->p->window_lock);
if (vout_Start(vout, cfg)
diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
index 59da8d95cd..b43d323fb0 100644
--- a/src/video_output/vout_internal.h
+++ b/src/video_output/vout_internal.h
@@ -45,6 +45,7 @@
*/
typedef struct {
vout_thread_t *vout;
+ vlc_clock_t *clock;
const video_format_t *fmt;
unsigned dpb_size;
vlc_mouse_event mouse_event;
@@ -64,6 +65,12 @@ struct vout_thread_sys_t
/* Splitter module if used */
char *splitter_name;
+ vlc_clock_t *clock;
+ float rate;
+ float spu_rate;
+ vlc_tick_t delay;
+ vlc_tick_t spu_delay;
+
/* */
video_format_t original; /* Original format ie coming from the decoder */
struct {
@@ -241,6 +248,7 @@ int vout_OpenWrapper(vout_thread_t *, const char *,
void vout_CloseWrapper(vout_thread_t *);
/* */
+void vout_SetSubpictureClock(vout_thread_t *vout, vlc_clock_t *clock);
int spu_ProcessMouse(spu_t *, const vlc_mouse_t *, const video_format_t *);
void spu_Attach( spu_t *, input_thread_t *input );
void spu_Detach( spu_t * );
@@ -257,6 +265,30 @@ void spu_SetHighlight(spu_t *, const vlc_spu_highlight_t*);
void vout_ChangePause( vout_thread_t *, bool b_paused, vlc_tick_t i_date );
/**
+ * This function will change the rate of the vout
+ * It is thread safe
+ */
+void vout_ChangeRate( vout_thread_t *, float rate );
+
+/**
+ * This function will change the delay of the vout
+ * It is thread safe
+ */
+void vout_ChangeDelay( vout_thread_t *, vlc_tick_t delay );
+
+/**
+ * This function will change the rate of the spu channel
+ * It is thread safe
+ */
+void vout_ChangeSpuRate( vout_thread_t *, float rate );
+/**
+ * This function will change the delay of the spu channel
+ * It is thread safe
+ */
+void vout_ChangeSpuDelay( vout_thread_t *, vlc_tick_t delay );
+
+
+/**
* Updates the pointing device state.
*/
void vout_MouseState(vout_thread_t *, const vlc_mouse_t *);
More information about the vlc-commits
mailing list