vlc | branch: master | Thomas Guillem <[email protected]> | 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 <[email protected]> * Gildas Bazin <[email protected]> @@ -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 *); _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
