Commit 4bfd8cb7 authored by Laurent Aimar's avatar Laurent Aimar

Added support for video filter that introduce latency (vout).

It is not yet perfect as the input is not warned of the latency of the vout.
parent 62f5a01b
...@@ -559,6 +559,10 @@ static picture_t *ThreadDisplayGetDecodedPicture(vout_thread_t *vout, ...@@ -559,6 +559,10 @@ static picture_t *ThreadDisplayGetDecodedPicture(vout_thread_t *vout,
const bool is_paused = vout->p->pause.is_on; const bool is_paused = vout->p->pause.is_on;
bool redisplay = is_paused && !now && vout->p->displayed.decoded; bool redisplay = is_paused && !now && vout->p->displayed.decoded;
mtime_t vfilter_delay = 0;
for (int i = 0; i < VOUT_FILTER_DELAYS; i++)
vfilter_delay = __MAX(vfilter_delay, vout->p->vfilter_delay[i]);
/* FIXME/XXX we must redisplay the last decoded picture (because /* FIXME/XXX we must redisplay the last decoded picture (because
* of potential vout updated, or filters update or SPU update) * of potential vout updated, or filters update or SPU update)
* For now a high update period is needed but it coulmd be removed * For now a high update period is needed but it coulmd be removed
...@@ -572,7 +576,9 @@ static picture_t *ThreadDisplayGetDecodedPicture(vout_thread_t *vout, ...@@ -572,7 +576,9 @@ static picture_t *ThreadDisplayGetDecodedPicture(vout_thread_t *vout,
picture_t *peek = picture_fifo_Peek(vout->p->decoder_fifo); picture_t *peek = picture_fifo_Peek(vout->p->decoder_fifo);
if (peek) { if (peek) {
*is_forced = peek->b_force || is_paused || now; *is_forced = peek->b_force || is_paused || now;
*deadline = (*is_forced ? date : peek->date) - vout_chrono_GetHigh(&vout->p->render); *deadline = (*is_forced ? date : peek->date) -
vout_chrono_GetHigh(&vout->p->render) -
vfilter_delay;
picture_Release(peek); picture_Release(peek);
} else { } else {
redisplay = true; redisplay = true;
...@@ -587,7 +593,7 @@ static picture_t *ThreadDisplayGetDecodedPicture(vout_thread_t *vout, ...@@ -587,7 +593,7 @@ static picture_t *ThreadDisplayGetDecodedPicture(vout_thread_t *vout,
} }
/* */ /* */
*is_forced = true; *is_forced = true;
*deadline = date - vout_chrono_GetHigh(&vout->p->render); *deadline = date - vout_chrono_GetHigh(&vout->p->render) - vfilter_delay;
} }
if (*deadline > VOUT_MWAIT_TOLERANCE) if (*deadline > VOUT_MWAIT_TOLERANCE)
*deadline -= VOUT_MWAIT_TOLERANCE; *deadline -= VOUT_MWAIT_TOLERANCE;
...@@ -658,6 +664,8 @@ static int ThreadDisplayPicture(vout_thread_t *vout, ...@@ -658,6 +664,8 @@ static int ThreadDisplayPicture(vout_thread_t *vout,
vlc_mutex_unlock(&vout->p->vfilter_lock); vlc_mutex_unlock(&vout->p->vfilter_lock);
if (!filtered) if (!filtered)
continue; continue;
vout->p->vfilter_delay[vout->p->vfilter_delay_index] = decoded->date - filtered->date;
vout->p->vfilter_delay_index = (vout->p->vfilter_delay_index + 1) % VOUT_FILTER_DELAYS;
} }
/* /*
...@@ -812,6 +820,10 @@ static void ThreadChangeFilters(vout_thread_t *vout, const char *filters) ...@@ -812,6 +820,10 @@ static void ThreadChangeFilters(vout_thread_t *vout, const char *filters)
msg_Err(vout, "Video filter chain creation failed"); msg_Err(vout, "Video filter chain creation failed");
vlc_mutex_unlock(&vout->p->vfilter_lock); vlc_mutex_unlock(&vout->p->vfilter_lock);
vout->p->vfilter_delay_index = 0;
for (int i = 0; i < VOUT_FILTER_DELAYS; i++)
vout->p->vfilter_delay[i] = 0;
} }
static void ThreadChangeSubFilters(vout_thread_t *vout, const char *filters) static void ThreadChangeSubFilters(vout_thread_t *vout, const char *filters)
...@@ -823,6 +835,13 @@ static void ThreadChangeSubMargin(vout_thread_t *vout, int margin) ...@@ -823,6 +835,13 @@ static void ThreadChangeSubMargin(vout_thread_t *vout, int margin)
spu_ChangeMargin(vout->p->p_spu, margin); spu_ChangeMargin(vout->p->p_spu, margin);
} }
static void ThreadFilterFlush(vout_thread_t *vout)
{
vlc_mutex_lock(&vout->p->vfilter_lock);
filter_chain_VideoFlush(vout->p->vfilter_chain);
vlc_mutex_unlock(&vout->p->vfilter_lock);
}
static void ThreadChangePause(vout_thread_t *vout, bool is_paused, mtime_t date) static void ThreadChangePause(vout_thread_t *vout, bool is_paused, mtime_t date)
{ {
assert(!vout->p->pause.is_on || !is_paused); assert(!vout->p->pause.is_on || !is_paused);
...@@ -839,6 +858,8 @@ static void ThreadChangePause(vout_thread_t *vout, bool is_paused, mtime_t date) ...@@ -839,6 +858,8 @@ static void ThreadChangePause(vout_thread_t *vout, bool is_paused, mtime_t date)
vout->p->displayed.decoded->date += duration; vout->p->displayed.decoded->date += duration;
spu_OffsetSubtitleDate(vout->p->p_spu, duration); spu_OffsetSubtitleDate(vout->p->p_spu, duration);
ThreadFilterFlush(vout);
} else { } else {
vout->p->step.timestamp = VLC_TS_INVALID; vout->p->step.timestamp = VLC_TS_INVALID;
vout->p->step.last = VLC_TS_INVALID; vout->p->step.last = VLC_TS_INVALID;
...@@ -863,6 +884,8 @@ static void ThreadFlush(vout_thread_t *vout, bool below, mtime_t date) ...@@ -863,6 +884,8 @@ static void ThreadFlush(vout_thread_t *vout, bool below, mtime_t date)
vout->p->displayed.timestamp = VLC_TS_INVALID; vout->p->displayed.timestamp = VLC_TS_INVALID;
} }
} }
ThreadFilterFlush(vout);
picture_fifo_Flush(vout->p->decoder_fifo, date, below); picture_fifo_Flush(vout->p->decoder_fifo, date, below);
} }
...@@ -988,6 +1011,9 @@ static int ThreadStart(vout_thread_t *vout, const vout_display_state_t *state) ...@@ -988,6 +1011,9 @@ static int ThreadStart(vout_thread_t *vout, const vout_display_state_t *state)
vout->p->vfilter_chain = vout->p->vfilter_chain =
filter_chain_New( vout, "video filter2", false, filter_chain_New( vout, "video filter2", false,
VoutVideoFilterAllocationSetup, NULL, vout); VoutVideoFilterAllocationSetup, NULL, vout);
vout->p->vfilter_delay_index = 0;
for (int i = 0; i < VOUT_FILTER_DELAYS; i++)
vout->p->vfilter_delay[i] = 0;
vout_display_state_t state_default; vout_display_state_t state_default;
if (!state) { if (!state) {
......
...@@ -48,6 +48,12 @@ ...@@ -48,6 +48,12 @@
*/ */
#define VOUT_MAX_PICTURES (20) #define VOUT_MAX_PICTURES (20)
/**
* Number of frames used to estimate the maximum filter chain latency.
* For performance, it is best to use a power of 2
*/
#define VOUT_FILTER_DELAYS (8)
/* */ /* */
struct vout_thread_sys_t struct vout_thread_sys_t
{ {
...@@ -126,6 +132,8 @@ struct vout_thread_sys_t ...@@ -126,6 +132,8 @@ struct vout_thread_sys_t
/* Video filter2 chain */ /* Video filter2 chain */
vlc_mutex_t vfilter_lock; vlc_mutex_t vfilter_lock;
filter_chain_t *vfilter_chain; filter_chain_t *vfilter_chain;
unsigned vfilter_delay_index;
mtime_t vfilter_delay[VOUT_FILTER_DELAYS];
/* */ /* */
vlc_mouse_t mouse; vlc_mouse_t mouse;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment