[vlc-devel] [PATCH 1/2] vout: add vout_Drain()
Thomas Guillem
thomas at gllm.fr
Wed Mar 15 15:33:30 CET 2017
vout_Drain() asks the vout thread to drain its queued pictures. This function
will wait for the last picture to be displayed.
Refs #18105
---
src/video_output/control.c | 33 +++++++++++++++++++++++++++++++--
src/video_output/control.h | 4 ++++
src/video_output/video_output.c | 28 ++++++++++++++++++++++++++++
src/video_output/vout_control.h | 5 +++++
src/video_output/vout_internal.h | 1 +
5 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/src/video_output/control.c b/src/video_output/control.c
index bbdb8948eb..078c510450 100644
--- a/src/video_output/control.c
+++ b/src/video_output/control.c
@@ -64,6 +64,7 @@ void vout_control_Init(vout_control_t *ctrl)
ctrl->is_dead = false;
ctrl->can_sleep = true;
ctrl->is_processing = false;
+ ctrl->is_draining = false;
ARRAY_INIT(ctrl->cmd);
}
@@ -98,15 +99,21 @@ void vout_control_WaitEmpty(vout_control_t *ctrl)
vlc_mutex_unlock(&ctrl->lock);
}
-void vout_control_Push(vout_control_t *ctrl, vout_control_cmd_t *cmd)
+static void vout_control_PushLocked(vout_control_t *ctrl,
+ vout_control_cmd_t *cmd)
{
- vlc_mutex_lock(&ctrl->lock);
if (!ctrl->is_dead) {
ARRAY_APPEND(ctrl->cmd, *cmd);
vlc_cond_signal(&ctrl->wait_request);
} else {
vout_control_cmd_Clean(cmd);
}
+}
+
+void vout_control_Push(vout_control_t *ctrl, vout_control_cmd_t *cmd)
+{
+ vlc_mutex_lock(&ctrl->lock);
+ vout_control_PushLocked(ctrl, cmd);
vlc_mutex_unlock(&ctrl->lock);
}
@@ -176,6 +183,28 @@ void vout_control_PushString(vout_control_t *ctrl, int type, const char *string)
vout_control_Push(ctrl, &cmd);
}
+void vout_control_Drained(vout_control_t *ctrl)
+{
+ vlc_mutex_lock(&ctrl->lock);
+ ctrl->is_draining = false;
+ vlc_cond_broadcast(&ctrl->wait_acknowledge);
+ vlc_mutex_unlock(&ctrl->lock);
+}
+
+void vout_control_Drain(vout_control_t *ctrl)
+{
+ vout_control_cmd_t cmd;
+
+ vout_control_cmd_Init(&cmd, VOUT_CONTROL_DRAIN);
+
+ vlc_mutex_lock(&ctrl->lock);
+ ctrl->is_draining = true;
+ vout_control_PushLocked(ctrl, &cmd);
+ while (ctrl->is_draining && !ctrl->is_dead)
+ vlc_cond_wait(&ctrl->wait_acknowledge, &ctrl->lock);
+ vlc_mutex_unlock(&ctrl->lock);
+}
+
int vout_control_Pop(vout_control_t *ctrl, vout_control_cmd_t *cmd,
mtime_t deadline)
{
diff --git a/src/video_output/control.h b/src/video_output/control.h
index 14eec3468d..c41a444aa6 100644
--- a/src/video_output/control.h
+++ b/src/video_output/control.h
@@ -48,6 +48,7 @@ enum {
VOUT_CONTROL_PAUSE,
VOUT_CONTROL_FLUSH, /* time */
+ VOUT_CONTROL_DRAIN, /* void */
VOUT_CONTROL_STEP, /* time_ptr */
VOUT_CONTROL_FULLSCREEN, /* bool */
@@ -115,6 +116,7 @@ typedef struct {
bool is_dead;
bool can_sleep;
bool is_processing;
+ bool is_draining;
DECL_ARRAY(vout_control_cmd_t) cmd;
} vout_control_t;
@@ -124,6 +126,7 @@ void vout_control_Clean(vout_control_t *);
/* controls outside of the vout thread */
void vout_control_WaitEmpty(vout_control_t *);
+void vout_control_Drain(vout_control_t *);
void vout_control_Push(vout_control_t *, vout_control_cmd_t *);
void vout_control_PushVoid(vout_control_t *, int type);
@@ -138,5 +141,6 @@ void vout_control_Wake(vout_control_t *);
/* control inside of the vout thread */
int vout_control_Pop(vout_control_t *, vout_control_cmd_t *, mtime_t deadline);
void vout_control_Dead(vout_control_t *);
+void vout_control_Drained(vout_control_t *);
#endif
diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c
index 155d6a9e30..16e3704f7c 100644
--- a/src/video_output/video_output.c
+++ b/src/video_output/video_output.c
@@ -332,6 +332,11 @@ void vout_Flush(vout_thread_t *vout, mtime_t date)
vout_control_WaitEmpty(&vout->p->control);
}
+void vout_Drain(vout_thread_t *vout)
+{
+ vout_control_Drain(&vout->p->control);
+}
+
bool vout_IsEmpty(vout_thread_t *vout)
{
picture_t *picture = picture_fifo_Peek(vout->p->decoder_fifo);
@@ -1067,6 +1072,25 @@ static int ThreadDisplayPicture(vout_thread_t *vout, mtime_t *deadline)
const mtime_t date = mdate();
const mtime_t render_delay = vout_chrono_GetHigh(&vout->p->render) + VOUT_MWAIT_TOLERANCE;
+ if (vout->p->draining && vout->p->displayed.next == NULL)
+ {
+ /* We reached the last picture to display */
+ if (vout->p->displayed.date <= VLC_TS_INVALID
+ || vout->p->displayed.date + render_delay <= date)
+ {
+ /* Notify the input (the caller of vout_Drain()) that the vout is
+ * drained */
+ vout_control_Drained(&vout->p->control);
+ }
+ else
+ {
+ /* Wait a little more before notifying the input, this function
+ * will be called again after the deadline. */
+ *deadline = vout->p->displayed.date + render_delay;
+ }
+ return VLC_EGENERIC;
+ }
+
bool drop_next_frame = frame_by_frame;
mtime_t date_next = VLC_TS_INVALID;
if (!paused && vout->p->displayed.next) {
@@ -1450,6 +1474,7 @@ static void ThreadInit(vout_thread_t *vout)
vout->p->is_late_dropped = var_InheritBool(vout, "drop-late-frames");
vout->p->pause.is_on = false;
vout->p->pause.date = VLC_TS_INVALID;
+ vout->p->draining = false;
vout_chrono_Init(&vout->p->render, 5, 10000); /* Arbitrary initial time */
}
@@ -1571,6 +1596,9 @@ static int ThreadControl(vout_thread_t *vout, vout_control_cmd_t cmd)
case VOUT_CONTROL_FLUSH:
ThreadFlush(vout, false, cmd.u.time);
break;
+ case VOUT_CONTROL_DRAIN:
+ vout->p->draining = true;
+ break;
case VOUT_CONTROL_STEP:
ThreadStep(vout, cmd.u.time_ptr);
break;
diff --git a/src/video_output/vout_control.h b/src/video_output/vout_control.h
index 25bae8e9aa..e12b8eb169 100644
--- a/src/video_output/vout_control.h
+++ b/src/video_output/vout_control.h
@@ -50,6 +50,11 @@ void vout_GetResetStatistic( vout_thread_t *p_vout, unsigned *pi_displayed,
*/
void vout_Flush( vout_thread_t *p_vout, mtime_t i_date );
+/**
+ * This function will wait for all queued pictures to be displayed.
+ */
+void vout_Drain( vout_thread_t *p_vout );
+
/*
* Cancel the vout, if cancel is true, it won't return any pictures after this
* call.
diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
index fec54f38eb..b441786089 100644
--- a/src/video_output/vout_internal.h
+++ b/src/video_output/vout_internal.h
@@ -74,6 +74,7 @@ struct vout_thread_sys_t
/* Thread & synchronization */
vlc_thread_t thread;
bool dead;
+ bool draining;
vout_control_t control;
/* */
--
2.11.0
More information about the vlc-devel
mailing list